rswim 2.1.0 → 2.2.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/.gitignore +1 -0
- data/CHANGELOG.md +2 -1
- data/Gemfile.lock +20 -20
- data/README.md +8 -2
- data/bin/encrypt +25 -0
- data/bin/run_node +8 -0
- data/lib/rswim/encryption.rb +43 -0
- data/lib/rswim/integration/udp/io_loop.rb +1 -31
- data/lib/rswim/integration/udp/sender.rb +37 -0
- data/lib/rswim/io_loop.rb +1 -1
- data/lib/rswim/node.rb +4 -2
- data/lib/rswim/serialization/encrypted/deserializer.rb +40 -0
- data/lib/rswim/serialization/encrypted/serializer.rb +41 -0
- data/lib/rswim/{integration → serialization/simple}/deserializer.rb +1 -1
- data/lib/rswim/{integration → serialization/simple}/serializer.rb +1 -1
- data/lib/rswim/version.rb +1 -1
- data/lib/rswim.rb +21 -1
- metadata +10 -6
- data/.ruby-version +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1acfab8998ff5ebd1919f16fd0e27c2f708224aedb004376ccbe2f5818bb6648
|
4
|
+
data.tar.gz: 5c85faa591b08d74d38b2fb091ee56b1e836af3e863005e51cbd55e35df2f255
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7c312893d1e1363675ad17ab97d7ad87dd016ab39ef4debb208016e970fdf9d8f1813fcfbe7f1c39ad8c0933765cf7b94fda82405dd732daa6bd9b3de2bba6e
|
7
|
+
data.tar.gz: 858683dc2c970daaefb085e467249a62b37a1e88e6ad556d5a944112bd51e463cda530168ee0a4abda0d35b175a3aceb031e4b4346dea44f1205c900b43647d4
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,4 @@
|
|
1
1
|
# 1.0.0 Complete implementation for UDP plus simple, human readable serialisation of messages
|
2
2
|
# 2.0.0 Piggyback custom state on the liveness propagation mechanism using `RSwim::Node#append_custom_state`
|
3
|
-
# 2.1.0 Use non-blocking I/O by means of `Fiber.shedule` with the scheduler provided by the Async gem
|
3
|
+
# 2.1.0 Use non-blocking I/O by means of `Fiber.shedule` with the scheduler provided by the Async gem
|
4
|
+
# 2.2.0 Encrypted messages between peers. Run UDP Sender in fiber instead of thread to make whole node single threaded.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rswim (2.
|
4
|
+
rswim (2.2.0)
|
5
5
|
async (~> 1.30)
|
6
6
|
slop (~> 4.9)
|
7
7
|
zeitwerk (~> 2.2)
|
@@ -15,12 +15,12 @@ GEM
|
|
15
15
|
timers (~> 4.1)
|
16
16
|
byebug (11.1.3)
|
17
17
|
coderay (1.1.3)
|
18
|
-
console (1.
|
18
|
+
console (1.14.0)
|
19
19
|
fiber-local
|
20
|
-
diff-lcs (1.
|
21
|
-
ffi (1.15.
|
20
|
+
diff-lcs (1.5.0)
|
21
|
+
ffi (1.15.5)
|
22
22
|
fiber-local (1.0.0)
|
23
|
-
formatador (
|
23
|
+
formatador (1.1.0)
|
24
24
|
fuubar (2.5.1)
|
25
25
|
rspec-core (~> 3.0)
|
26
26
|
ruby-progressbar (~> 1.4)
|
@@ -38,7 +38,7 @@ GEM
|
|
38
38
|
guard (~> 2.1)
|
39
39
|
guard-compat (~> 1.1)
|
40
40
|
rspec (>= 2.99.0, < 4.0)
|
41
|
-
listen (3.7.
|
41
|
+
listen (3.7.1)
|
42
42
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
43
43
|
rb-inotify (~> 0.9, >= 0.9.10)
|
44
44
|
lumberjack (1.2.8)
|
@@ -52,28 +52,28 @@ GEM
|
|
52
52
|
coderay (~> 1.1)
|
53
53
|
method_source (~> 1.0)
|
54
54
|
rake (12.3.3)
|
55
|
-
rb-fsevent (0.11.
|
55
|
+
rb-fsevent (0.11.1)
|
56
56
|
rb-inotify (0.10.1)
|
57
57
|
ffi (~> 1.0)
|
58
|
-
rspec (3.
|
59
|
-
rspec-core (~> 3.
|
60
|
-
rspec-expectations (~> 3.
|
61
|
-
rspec-mocks (~> 3.
|
62
|
-
rspec-core (3.
|
63
|
-
rspec-support (~> 3.
|
64
|
-
rspec-expectations (3.
|
58
|
+
rspec (3.11.0)
|
59
|
+
rspec-core (~> 3.11.0)
|
60
|
+
rspec-expectations (~> 3.11.0)
|
61
|
+
rspec-mocks (~> 3.11.0)
|
62
|
+
rspec-core (3.11.0)
|
63
|
+
rspec-support (~> 3.11.0)
|
64
|
+
rspec-expectations (3.11.0)
|
65
65
|
diff-lcs (>= 1.2.0, < 2.0)
|
66
|
-
rspec-support (~> 3.
|
67
|
-
rspec-mocks (3.
|
66
|
+
rspec-support (~> 3.11.0)
|
67
|
+
rspec-mocks (3.11.0)
|
68
68
|
diff-lcs (>= 1.2.0, < 2.0)
|
69
|
-
rspec-support (~> 3.
|
70
|
-
rspec-support (3.
|
69
|
+
rspec-support (~> 3.11.0)
|
70
|
+
rspec-support (3.11.0)
|
71
71
|
ruby-progressbar (1.11.0)
|
72
72
|
shellany (0.0.1)
|
73
73
|
slop (4.9.1)
|
74
|
-
thor (1.1
|
74
|
+
thor (1.2.1)
|
75
75
|
timers (4.3.3)
|
76
|
-
zeitwerk (2.4
|
76
|
+
zeitwerk (2.5.4)
|
77
77
|
|
78
78
|
PLATFORMS
|
79
79
|
ruby
|
data/README.md
CHANGED
@@ -4,11 +4,14 @@ RSwim is a Ruby implementation of the SWIM gossip protocol, a mechanism for disc
|
|
4
4
|
|
5
5
|
It is an implementation inspired by the original [SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol](https://www.cs.cornell.edu/projects/Quicksilver/public_pdfs/SWIM.pdf) paper by Abhinandan Das, Indranil Gupta, Ashish Motivala.
|
6
6
|
|
7
|
-
The implementation is kept intentionally simple and
|
7
|
+
The implementation is kept intentionally simple and includes only the features described in the paper along with a few additions after version 2.0.0:
|
8
|
+
|
9
|
+
- The ability to piggyback custom state on the liveness propagation mechanism was added in version 2.0.0, see `RSwim::Node#append_custom_state`
|
10
|
+
- Encryption of messsages between peers based on a shared secret was introduced in version 2.2.0, see module `RSwim::Serialization::Encrypted`
|
8
11
|
|
9
12
|
No attempts have been made to address known security issues such as Byzantine attacks.
|
10
13
|
|
11
|
-
Currently RSwim runs on UDP
|
14
|
+
Currently RSwim runs on UDP. In the unencrypted mode it uses a custom, human readable serialization format. Peers in unencrypted mode cannot communicate with peers in encrypted mode.
|
12
15
|
|
13
16
|
|
14
17
|
## Installation
|
@@ -34,6 +37,9 @@ Example:
|
|
34
37
|
```ruby
|
35
38
|
require 'rswim'
|
36
39
|
|
40
|
+
RSwim.encrypted = true
|
41
|
+
RSwim.shared_secret = 'santa 2000'
|
42
|
+
|
37
43
|
port = 4545
|
38
44
|
|
39
45
|
# known, running nodes to connect with initially.
|
data/bin/encrypt
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby --jit
|
2
|
+
|
3
|
+
require 'openssl'
|
4
|
+
require 'console'
|
5
|
+
|
6
|
+
cipher = OpenSSL::Cipher::AES256.new :CBC
|
7
|
+
cipher.encrypt
|
8
|
+
iv = cipher.random_iv
|
9
|
+
cipher.key = key = Digest::SHA256.digest 'SecretPassword'
|
10
|
+
cipher_text = cipher.update('This is a secret message') + cipher.final
|
11
|
+
|
12
|
+
Console.logger.info cipher_text, 'got this after encrypting'
|
13
|
+
|
14
|
+
begin
|
15
|
+
decipher = OpenSSL::Cipher::AES256.new :CBC
|
16
|
+
decipher.decrypt
|
17
|
+
decipher.iv = iv # previously saved
|
18
|
+
decipher.key = Digest::SHA256.digest 'mismatch'
|
19
|
+
plain_text = decipher.update(cipher_text) + decipher.final
|
20
|
+
|
21
|
+
Console.logger.info plain_text, 'got this after decrypting'
|
22
|
+
rescue OpenSSL::Cipher::CipherError => e
|
23
|
+
Console.logger.error('Error while decrypting')
|
24
|
+
Console.logger.failure(decipher, e)
|
25
|
+
end
|
data/bin/run_node
CHANGED
@@ -8,6 +8,8 @@ PORT = 4545
|
|
8
8
|
opts = Slop.parse do |o|
|
9
9
|
o.array '-s', '--seeds', 'a comma separated list of seed nodes'
|
10
10
|
o.bool '-d', '--debug', 'turn on debug logging'
|
11
|
+
o.bool '-e', '--encrypted', 'use encrypted mode'
|
12
|
+
o.string '--secret', 'shared secret for encrypted mode', default: 'santa 2000'
|
11
13
|
o.on '--help' do
|
12
14
|
puts o
|
13
15
|
exit
|
@@ -21,6 +23,12 @@ end
|
|
21
23
|
puts "Ruby version: #{RUBY_VERSION}"
|
22
24
|
|
23
25
|
RSwim::Logger.level = ::Logger::DEBUG if opts.debug?
|
26
|
+
|
27
|
+
if opts.encrypted?
|
28
|
+
RSwim.encrypted = true
|
29
|
+
RSwim.shared_secret = opts[:secret]
|
30
|
+
end
|
31
|
+
|
24
32
|
seed_hosts = opts[:seeds]
|
25
33
|
abort 'EOF' if seed_hosts.nil?
|
26
34
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module RSwim
|
2
|
+
module Encryption
|
3
|
+
class << self
|
4
|
+
def encrypt(message)
|
5
|
+
message = message.dup.force_encoding('UTF-8')
|
6
|
+
salt = cipher.random_iv
|
7
|
+
cipher_text = cipher.update(message) + cipher.final
|
8
|
+
[cipher_text, salt]
|
9
|
+
rescue StandardError => e
|
10
|
+
raise Error, "Failed to encrypt: #{e.message}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def decrypt(cipher_text, salt)
|
14
|
+
decipher.iv = salt
|
15
|
+
message = decipher.update(cipher_text) + decipher.final
|
16
|
+
message.force_encoding('UTF-8')
|
17
|
+
rescue StandardError => e
|
18
|
+
raise Error, "Failed to decrypt: #{e.message}"
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def cipher
|
24
|
+
@_cipher ||= begin
|
25
|
+
cipher = OpenSSL::Cipher::AES256.new :CBC
|
26
|
+
cipher.encrypt
|
27
|
+
cipher.key = Digest::SHA256.digest(RSwim.shared_secret)
|
28
|
+
cipher
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def decipher
|
33
|
+
@_decipher ||= begin
|
34
|
+
cipher = OpenSSL::Cipher::AES256.new :CBC
|
35
|
+
cipher.decrypt
|
36
|
+
cipher.key = Digest::SHA256.digest(RSwim.shared_secret)
|
37
|
+
cipher
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -3,36 +3,6 @@
|
|
3
3
|
module RSwim
|
4
4
|
module Integration
|
5
5
|
module UDP
|
6
|
-
class Sender
|
7
|
-
def initialize(port, out_q)
|
8
|
-
@out_q = out_q
|
9
|
-
@port = port
|
10
|
-
@out_s = UDPSocket.new
|
11
|
-
end
|
12
|
-
|
13
|
-
def run
|
14
|
-
Async do
|
15
|
-
loop do
|
16
|
-
wire_messages = @out_q.pop
|
17
|
-
wire_messages.each do |(host, wire_message)|
|
18
|
-
logger.debug "about to send message to #{host} on port #{@port}"
|
19
|
-
Fiber.schedule do
|
20
|
-
@out_s.send(wire_message, 0, host, @port)
|
21
|
-
rescue StandardError => e
|
22
|
-
logger.debug("Error while sending: #{e}")
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def logger
|
32
|
-
@_logger ||= RSwim::Logger.new(self.class, $stderr)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
6
|
class IOLoop < RSwim::IOLoop
|
37
7
|
def initialize(agent, serializer, deserializer, directory, sleep_time_seconds, my_host, port)
|
38
8
|
super(agent, serializer, deserializer, directory, sleep_time_seconds)
|
@@ -46,7 +16,7 @@ module RSwim
|
|
46
16
|
@in_s = UDPSocket.new
|
47
17
|
@in_s.bind(@my_host, @port)
|
48
18
|
@out_q = Queue.new
|
49
|
-
|
19
|
+
Fiber.schedule { Sender.new(@port, @out_q).run }
|
50
20
|
end
|
51
21
|
|
52
22
|
def read
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSwim
|
4
|
+
module Integration
|
5
|
+
module UDP
|
6
|
+
class Sender
|
7
|
+
def initialize(port, out_q)
|
8
|
+
@out_q = out_q
|
9
|
+
@port = port
|
10
|
+
@out_s = UDPSocket.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
Async do
|
15
|
+
loop do
|
16
|
+
wire_messages = @out_q.pop
|
17
|
+
wire_messages.each do |(host, wire_message)|
|
18
|
+
logger.debug "about to send message to #{host} on port #{@port}"
|
19
|
+
Fiber.schedule do
|
20
|
+
@out_s.send(wire_message, 0, host, @port)
|
21
|
+
rescue StandardError => e
|
22
|
+
logger.debug("Error while sending: #{e}")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def logger
|
32
|
+
@_logger ||= RSwim::Logger.new(self.class, $stderr)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/rswim/io_loop.rb
CHANGED
data/lib/rswim/node.rb
CHANGED
@@ -7,11 +7,13 @@ module RSwim
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def initialize(my_host, seed_hosts, t_ms, r_ms)
|
10
|
+
RSwim.validate_config!
|
10
11
|
@my_host = my_host
|
11
12
|
@directory = Directory.new
|
12
13
|
@my_id = @directory.id(@my_host)
|
13
|
-
|
14
|
-
@
|
14
|
+
serialization = RSwim.encrypted ? Serialization::Encrypted : Serialization::Simple
|
15
|
+
@deserializer = serialization::Deserializer.new(@directory, @my_id)
|
16
|
+
@serializer = serialization::Serializer.new(@directory)
|
15
17
|
@seed_ids = seed_hosts.map { |host| @directory.id(host) }
|
16
18
|
@t_ms = t_ms
|
17
19
|
@r_ms = r_ms
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSwim
|
4
|
+
module Serialization::Encrypted
|
5
|
+
class Deserializer
|
6
|
+
def initialize(directory, my_id)
|
7
|
+
@directory = directory
|
8
|
+
@my_id = my_id
|
9
|
+
end
|
10
|
+
|
11
|
+
def deserialize(sender_host, wire_message)
|
12
|
+
outer = JSON.parse(wire_message)
|
13
|
+
cipher_text, salt = outer.values_at('message', 'salt').map { |s| Base64.decode64(s) }
|
14
|
+
inner = JSON.parse(Encryption.decrypt(cipher_text, salt), symbolize_names: true)
|
15
|
+
|
16
|
+
from = @directory.id(sender_host)
|
17
|
+
payload = {}
|
18
|
+
payload[:target_id] = @directory.id(inner[:target]) unless inner[:target].nil?
|
19
|
+
payload[:updates] = inner[:updates].to_a.map do |u|
|
20
|
+
UpdateEntry.new(
|
21
|
+
@directory.id(u[:host]),
|
22
|
+
u[:status].to_sym,
|
23
|
+
u[:incarnation_number].to_i,
|
24
|
+
u[:custom_state]
|
25
|
+
)
|
26
|
+
end
|
27
|
+
Message.new(@my_id, from, inner[:type].to_sym, payload)
|
28
|
+
rescue StandardError => e
|
29
|
+
logger.debug("Failed to parse wire message")
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def logger
|
36
|
+
@_logger ||= RSwim::Logger.new(self.class, $stderr)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSwim
|
4
|
+
module Serialization::Encrypted
|
5
|
+
class Serializer
|
6
|
+
def initialize(directory)
|
7
|
+
@directory = directory
|
8
|
+
end
|
9
|
+
|
10
|
+
def serialize(message)
|
11
|
+
unencrypted = serialize_unencrypted(message)
|
12
|
+
cipher_text, salt = Encryption.encrypt(unencrypted).map { |s| Base64.encode64(s) }
|
13
|
+
{ message: cipher_text, salt: salt }.to_json
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def logger
|
19
|
+
@_logger ||= RSwim::Logger.new(self.class, STDERR)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def serialize_unencrypted(message)
|
25
|
+
out = {}
|
26
|
+
out[:type] = message.type
|
27
|
+
out[:target] = @directory.host(message.payload[:target_id]) if message.type == :ping_req
|
28
|
+
out[:updates] = message.payload[:updates].to_a.map do |update|
|
29
|
+
{
|
30
|
+
host: @directory.host(update.member_id),
|
31
|
+
status: update.status,
|
32
|
+
incarnation_number: update.incarnation_number,
|
33
|
+
custom_state: update.custom_state
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
out.to_json
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/rswim/version.rb
CHANGED
data/lib/rswim.rb
CHANGED
@@ -4,8 +4,14 @@ require 'logger'
|
|
4
4
|
require 'socket'
|
5
5
|
require 'zeitwerk'
|
6
6
|
require 'async'
|
7
|
+
require 'openssl'
|
8
|
+
require 'base64'
|
7
9
|
|
8
|
-
|
10
|
+
cipher = OpenSSL::Cipher::AES256.new :CBC
|
11
|
+
cipher.encrypt
|
12
|
+
iv = cipher.random_iv
|
13
|
+
cipher.key = key = Digest::SHA256.digest 'SecretPassword'
|
14
|
+
cipher_text = cipher.update('This is a secret message') + cipher.final
|
9
15
|
|
10
16
|
class MyInflector < Zeitwerk::Inflector
|
11
17
|
def camelize(basename, _abspath)
|
@@ -31,5 +37,19 @@ module RSwim
|
|
31
37
|
# Roundtrip time, millis
|
32
38
|
R_MS = 10_000
|
33
39
|
|
40
|
+
class << self
|
41
|
+
attr_accessor :encrypted, :shared_secret
|
42
|
+
|
43
|
+
def validate_config!
|
44
|
+
validate_shared_secret! if @encrypted
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def validate_shared_secret!
|
49
|
+
raise Error, 'Encrypted mode was set, but no shared secret configured' if @shared_secret.nil?
|
50
|
+
raise Error, 'Shared secret too short' if @shared_secret.length < 8
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
34
54
|
class Error < StandardError; end
|
35
55
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rswim
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Erik Madsen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: zeitwerk
|
@@ -147,7 +147,6 @@ extra_rdoc_files: []
|
|
147
147
|
files:
|
148
148
|
- ".gitignore"
|
149
149
|
- ".rspec"
|
150
|
-
- ".ruby-version"
|
151
150
|
- ".travis.yml"
|
152
151
|
- CHANGELOG.md
|
153
152
|
- Gemfile
|
@@ -158,15 +157,16 @@ files:
|
|
158
157
|
- Rakefile
|
159
158
|
- bin/async_loop
|
160
159
|
- bin/console
|
160
|
+
- bin/encrypt
|
161
161
|
- bin/run_node
|
162
162
|
- bin/setup
|
163
163
|
- lib/rswim.rb
|
164
164
|
- lib/rswim/agent.rb
|
165
165
|
- lib/rswim/directory.rb
|
166
|
-
- lib/rswim/
|
167
|
-
- lib/rswim/integration/serializer.rb
|
166
|
+
- lib/rswim/encryption.rb
|
168
167
|
- lib/rswim/integration/udp/io_loop.rb
|
169
168
|
- lib/rswim/integration/udp/node.rb
|
169
|
+
- lib/rswim/integration/udp/sender.rb
|
170
170
|
- lib/rswim/io_loop.rb
|
171
171
|
- lib/rswim/logger.rb
|
172
172
|
- lib/rswim/member/ack_responder.rb
|
@@ -191,6 +191,10 @@ files:
|
|
191
191
|
- lib/rswim/node.rb
|
192
192
|
- lib/rswim/pipe.rb
|
193
193
|
- lib/rswim/protocol_state.rb
|
194
|
+
- lib/rswim/serialization/encrypted/deserializer.rb
|
195
|
+
- lib/rswim/serialization/encrypted/serializer.rb
|
196
|
+
- lib/rswim/serialization/simple/deserializer.rb
|
197
|
+
- lib/rswim/serialization/simple/serializer.rb
|
194
198
|
- lib/rswim/status_report.rb
|
195
199
|
- lib/rswim/update_entry.rb
|
196
200
|
- lib/rswim/version.rb
|
@@ -219,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
219
223
|
- !ruby/object:Gem::Version
|
220
224
|
version: '0'
|
221
225
|
requirements: []
|
222
|
-
rubygems_version: 3.
|
226
|
+
rubygems_version: 3.3.3
|
223
227
|
signing_key:
|
224
228
|
specification_version: 4
|
225
229
|
summary: Ruby implementation of the SWIM gossip protocol
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
3.0.2
|