arf 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/LICENSE.txt +21 -0
  4. data/Rakefile +12 -0
  5. data/lib/arf/configuration.rb +67 -0
  6. data/lib/arf/context.rb +170 -0
  7. data/lib/arf/errors.rb +10 -0
  8. data/lib/arf/io/buffer.rb +25 -0
  9. data/lib/arf/io/compression.rb +44 -0
  10. data/lib/arf/io/limit_reader.rb +30 -0
  11. data/lib/arf/observer.rb +29 -0
  12. data/lib/arf/proto/array.rb +31 -0
  13. data/lib/arf/proto/boolean.rb +15 -0
  14. data/lib/arf/proto/bytes.rb +35 -0
  15. data/lib/arf/proto/decoder.rb +31 -0
  16. data/lib/arf/proto/encoder.rb +71 -0
  17. data/lib/arf/proto/float.rb +48 -0
  18. data/lib/arf/proto/map.rb +49 -0
  19. data/lib/arf/proto/registry.rb +27 -0
  20. data/lib/arf/proto/scalar.rb +55 -0
  21. data/lib/arf/proto/string.rb +36 -0
  22. data/lib/arf/proto/struct.rb +84 -0
  23. data/lib/arf/proto/types.rb +67 -0
  24. data/lib/arf/proto/union.rb +25 -0
  25. data/lib/arf/proto.rb +17 -0
  26. data/lib/arf/reactor.rb +270 -0
  27. data/lib/arf/rpc/base_message.rb +119 -0
  28. data/lib/arf/rpc/client_base.rb +110 -0
  29. data/lib/arf/rpc/end_stream.rb +9 -0
  30. data/lib/arf/rpc/enum.rb +51 -0
  31. data/lib/arf/rpc/message_kind.rb +27 -0
  32. data/lib/arf/rpc/metadata.rb +120 -0
  33. data/lib/arf/rpc/method_meta.rb +42 -0
  34. data/lib/arf/rpc/request.rb +39 -0
  35. data/lib/arf/rpc/responder.rb +186 -0
  36. data/lib/arf/rpc/response.rb +46 -0
  37. data/lib/arf/rpc/service_base.rb +137 -0
  38. data/lib/arf/rpc/start_stream.rb +9 -0
  39. data/lib/arf/rpc/stream_error.rb +23 -0
  40. data/lib/arf/rpc/stream_item.rb +16 -0
  41. data/lib/arf/rpc/stream_metadata.rb +16 -0
  42. data/lib/arf/rpc/struct.rb +255 -0
  43. data/lib/arf/rpc.rb +19 -0
  44. data/lib/arf/server.rb +123 -0
  45. data/lib/arf/status.rb +75 -0
  46. data/lib/arf/types/array_type.rb +24 -0
  47. data/lib/arf/types/base_type.rb +14 -0
  48. data/lib/arf/types/coercion.rb +36 -0
  49. data/lib/arf/types/in_out_stream.rb +28 -0
  50. data/lib/arf/types/input_stream.rb +8 -0
  51. data/lib/arf/types/map_type.rb +32 -0
  52. data/lib/arf/types/mixin.rb +29 -0
  53. data/lib/arf/types/output_stream.rb +8 -0
  54. data/lib/arf/types/streamer.rb +21 -0
  55. data/lib/arf/types.rb +69 -0
  56. data/lib/arf/version.rb +5 -0
  57. data/lib/arf/wire/base_connection.rb +177 -0
  58. data/lib/arf/wire/client.rb +101 -0
  59. data/lib/arf/wire/encoding.rb +49 -0
  60. data/lib/arf/wire/error_code.rb +35 -0
  61. data/lib/arf/wire/errors.rb +88 -0
  62. data/lib/arf/wire/frame.rb +111 -0
  63. data/lib/arf/wire/frame_kind.rb +23 -0
  64. data/lib/arf/wire/frame_reader.rb +104 -0
  65. data/lib/arf/wire/frames/base_frame.rb +108 -0
  66. data/lib/arf/wire/frames/configuration_frame.rb +33 -0
  67. data/lib/arf/wire/frames/data_frame.rb +21 -0
  68. data/lib/arf/wire/frames/go_away_frame.rb +29 -0
  69. data/lib/arf/wire/frames/make_stream_frame.rb +15 -0
  70. data/lib/arf/wire/frames/ping_frame.rb +18 -0
  71. data/lib/arf/wire/frames/reset_stream_frame.rb +19 -0
  72. data/lib/arf/wire/frames.rb +9 -0
  73. data/lib/arf/wire/server/peer.rb +85 -0
  74. data/lib/arf/wire/server.rb +63 -0
  75. data/lib/arf/wire/stream/state.rb +69 -0
  76. data/lib/arf/wire/stream.rb +128 -0
  77. data/lib/arf/wire/wait_signal.rb +24 -0
  78. data/lib/arf/wire.rb +14 -0
  79. data/lib/arf.rb +46 -0
  80. metadata +195 -0
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arf
4
+ module Wire
5
+ class Server
6
+ class Peer < Wire::BaseConnection
7
+ def initialize(server)
8
+ super()
9
+ @server = server
10
+ @id = @server.register_peer(self)
11
+ @log = Arf.logger.with_fields(subsystem: "Peer", id: @id)
12
+ end
13
+
14
+ def close
15
+ super
16
+ @server.unregister_peer(@id)
17
+ end
18
+
19
+ def handle_configuration(fr)
20
+ return protocol_error! if @configured
21
+
22
+ resp = ConfigurationFrame.new.tap(&:ack!)
23
+
24
+ if fr.compression_brotli?
25
+ @compression = :brotli
26
+ resp.compression_brotli!
27
+ elsif fr.compression_gzip?
28
+ @compression = :gzip
29
+ resp.compression_gzip!
30
+ end
31
+
32
+ resp.max_concurrent_streams = 0 # TODO
33
+
34
+ @configured = true
35
+ @log.debug("Configuration OK")
36
+ dispatch(resp)
37
+ end
38
+
39
+ def handle_go_away(fr)
40
+ return protocol_error! unless @configured
41
+
42
+ # client intends to disconnect
43
+ cancel_streams(fr.error_code)
44
+ close_connection_after_writing
45
+ end
46
+
47
+ def handle_make_stream(fr)
48
+ return protocol_error! unless @configured
49
+ return protocol_error! unless fetch_stream(fr.stream_id).nil?
50
+
51
+ @streams_monitor.synchronize do
52
+ @streams[fr.stream_id] = Stream.new(fr.stream_id, self)
53
+ end
54
+ @log.debug("Async dispatch handle_stream")
55
+ Reactor.post { @server.handle_stream(@streams[fr.stream_id]) }
56
+ end
57
+
58
+ def handle_data(fr)
59
+ return protocol_error! unless @configured
60
+
61
+ str = fetch_stream(fr.stream_id)
62
+ return reset_stream(fr.stream_id, ERROR_CODE_PROTOCOL_ERROR) unless str
63
+
64
+ str.handle_data(fr)
65
+ end
66
+
67
+ def handle_reset_stream(fr)
68
+ return protocol_error! unless @configured
69
+
70
+ str = fetch_stream(fr.stream_id)
71
+ return protocol_error! unless str
72
+
73
+ str.handle_reset_stream(fr)
74
+ end
75
+
76
+ def reset_stream(id, code)
77
+ dispatch_frame(ResetStreamFrame) do |r|
78
+ r.stream_id = id
79
+ r.error_code = code
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "server/peer"
4
+
5
+ module Arf
6
+ module Wire
7
+ class Server
8
+ def initialize(handler)
9
+ @peers = {}
10
+ @peer_id = 0
11
+ @peers_monitor = Monitor.new
12
+ @handler = handler
13
+ @logger = Arf.logger.with_fields(subsystem: "Server")
14
+ end
15
+
16
+ def register_peer(peer)
17
+ @logger.debug("Registered peer", peer: peer.class.name)
18
+ @peers_monitor.synchronize do
19
+ id = @peer_id
20
+ @peer_id += 1
21
+ @peers[id] = peer
22
+ id
23
+ end
24
+ end
25
+
26
+ def unregister_peer(id)
27
+ @peers_monitor.synchronize do
28
+ @peers.delete(id)
29
+ end
30
+ end
31
+
32
+ def peer_by_id(id)
33
+ @peers_monitor.synchronize do
34
+ @peers[id]
35
+ end
36
+ end
37
+
38
+ def handle_stream(str)
39
+ @logger.debug("Handle Stream received")
40
+ @handler&.handle_stream(str)
41
+ end
42
+
43
+ def cancel_stream(str) = @handler&.cancel_stream(str)
44
+
45
+ def shutdown
46
+ return unless @tcp_server
47
+
48
+ @tcp_server.close
49
+ Arf::Reactor.detach(@tcp_server)
50
+ @peers_monitor.synchronize do
51
+ @peers.each_value { _1.go_away! ERROR_CODE_NO_ERROR, terminate: true }
52
+ end
53
+ end
54
+
55
+ def run
56
+ config = Arf.config
57
+ @tcp_server = TCPServer.new(config.bind_address, config.bind_port)
58
+ @tcp_server.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
59
+ Arf::Reactor.attach_server(@tcp_server, Peer, self)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arf
4
+ module Wire
5
+ class Stream
6
+ class State
7
+ attr_reader :code
8
+ attr_accessor :error
9
+
10
+ def initialize
11
+ @code = :open
12
+ @error = nil
13
+ end
14
+
15
+ def close
16
+ @code = :closed
17
+ end
18
+
19
+ def close_local
20
+ @code = case @code
21
+ when :open then :half_closed_local
22
+ when :half_closed_local then :half_closed_local
23
+ when :half_closed_remote, :closed then :closed
24
+ end
25
+ end
26
+
27
+ def close_remote
28
+ @code = case @code
29
+ when :open then :half_closed_remote
30
+ when :half_closed_local, :closed then :closed
31
+ when :half_closed_remote then :half_closed_remote
32
+ end
33
+ end
34
+
35
+ def closed? = (@code == :closed)
36
+ def remote_closed? = (@code == :half_closed_remote)
37
+ def local_closed? = (@code == :half_closed_local)
38
+
39
+ def may_reset_stream?
40
+ raise @error if @error
41
+ raise ClosedStreamError if closed?
42
+
43
+ true
44
+ end
45
+
46
+ def may_receive_data?
47
+ raise @error if @error
48
+ raise ClosedStreamError if closed? || remote_closed?
49
+
50
+ true
51
+ end
52
+
53
+ def may_send_reset_stream?
54
+ raise @error if @error
55
+ raise ClosedStreamError if closed? || local_closed?
56
+
57
+ true
58
+ end
59
+
60
+ def may_send_data?
61
+ raise @error if @error
62
+ raise ClosedStreamError if closed? || local_closed?
63
+
64
+ true
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "stream/state"
4
+
5
+ module Arf
6
+ module Wire
7
+ class Stream
8
+ attr_reader :id, :state
9
+ attr_accessor :external_id
10
+
11
+ def initialize(id, driver)
12
+ @id = id
13
+ @driver = driver
14
+ @state = State.new
15
+ @tmp_data = StringIO.new
16
+ @to_read_monitor = Monitor.new
17
+ @to_read = Queue.new
18
+ @handler = nil
19
+ @log = Arf.logger.with_fields(component: "Stream", driver: @driver.class.name)
20
+ end
21
+
22
+ def attach_handler(handler)
23
+ @log.debug("Attached handler", handler:)
24
+ @handler = handler
25
+ @to_read_monitor.synchronize do
26
+ @handler.handle_data(@to_read.shift) until @to_read.empty?
27
+ end
28
+ end
29
+
30
+ def handle_reset_stream(fr)
31
+ # return if @state.closed? # Ignore resets when stream is closed
32
+ @state.may_reset_stream?
33
+ @state.close
34
+ @state.error = StreamResetError.new(fr.error_code)
35
+ rescue ClosedStreamError
36
+ reset!(Wire::ERROR_CODE_STREAM_CLOSED)
37
+ end
38
+
39
+ def handle_data(fr)
40
+ @state.may_receive_data?
41
+ data = case fr.payload
42
+ when StringIO then fr.payload.string
43
+ when String then fr.payload
44
+ else fr.payload.to_s
45
+ end
46
+
47
+ @tmp_data.write(data)
48
+
49
+ if fr.end_data? && @tmp_data.length.positive?
50
+ @tmp_data.rewind
51
+ @to_read_monitor.synchronize do
52
+ if @handler && @to_read.empty?
53
+ @handler.handle_data(@tmp_data)
54
+ else
55
+ @to_read << @tmp_data
56
+ end
57
+ @tmp_data = StringIO.new
58
+ end
59
+ end
60
+ @state.close_remote if fr.end_stream?
61
+ rescue ClosedStreamError
62
+ reset!(Wire::ERROR_CODE_STREAM_CLOSED)
63
+ end
64
+
65
+ def reset!(code)
66
+ write(ResetStreamFrame) do |fr|
67
+ fr.stream_id = @id
68
+ fr.error_code = code
69
+ end
70
+ end
71
+
72
+ def reset(code)
73
+ @state.may_send_reset_stream?
74
+ @state.close
75
+ reset!(code)
76
+ end
77
+
78
+ def close_local
79
+ @state.may_send_data?
80
+ @state.close_local
81
+ write(DataFrame) do |fr|
82
+ fr.end_data!
83
+ fr.end_stream!
84
+ end
85
+ end
86
+
87
+ def read
88
+ raise @state.error if @state.error
89
+
90
+ begin
91
+ val = @to_read.shift(true)
92
+ return val if val
93
+ rescue ThreadError
94
+ nil
95
+ end
96
+
97
+ @state.may_receive_data?
98
+ nil
99
+ end
100
+
101
+ def read_blocking
102
+ raise @state.error if @state.error
103
+
104
+ val = @to_read.shift
105
+ return val if val
106
+
107
+ nil
108
+ end
109
+
110
+ def write(type, &)
111
+ @log.debug("Dispatching", type:)
112
+ inst = type.new(&)
113
+ inst.stream_id = @id if inst.respond_to?(:stream_id=)
114
+ @driver.dispatch(inst)
115
+ end
116
+
117
+ def write_data(value, end_stream: false)
118
+ @state.may_send_data?
119
+
120
+ @log.dump("Writing", value, source: caller[0])
121
+ Wire.data_frames_from_buffer(@id, value, end_stream:).each do |fr|
122
+ @driver.dispatch(fr)
123
+ end
124
+ @state.close_local if end_stream
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Arf
4
+ module Wire
5
+ class WaitSignal
6
+ def initialize
7
+ @mutex = Mutex.new
8
+ @cond = Thread::ConditionVariable.new
9
+ end
10
+
11
+ def wait
12
+ @mutex.synchronize do
13
+ @cond.wait(@mutex)
14
+ end
15
+ end
16
+
17
+ def broadcast
18
+ @mutex.synchronize do
19
+ @cond.broadcast
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
data/lib/arf/wire.rb ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "wire/encoding"
4
+ require_relative "wire/wait_signal"
5
+ require_relative "wire/frame_kind"
6
+ require_relative "wire/error_code"
7
+ require_relative "wire/errors"
8
+ require_relative "wire/frame"
9
+ require_relative "wire/frames"
10
+ require_relative "wire/base_connection"
11
+ require_relative "wire/client"
12
+ require_relative "wire/frame_reader"
13
+ require_relative "wire/stream"
14
+ require_relative "wire/server"
data/lib/arf.rb ADDED
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "stringio"
4
+ require "securerandom"
5
+ require "openssl"
6
+ require "monitor"
7
+
8
+ Thread.abort_on_exception = true
9
+
10
+ require "zlib"
11
+ require "brotli"
12
+ require "logrb"
13
+ require "nio"
14
+ require "concurrent"
15
+
16
+ require_relative "arf/version"
17
+ require_relative "arf/configuration"
18
+ require_relative "arf/reactor"
19
+ require_relative "arf/errors"
20
+ require_relative "arf/io/buffer"
21
+ require_relative "arf/io/limit_reader"
22
+ require_relative "arf/io/compression"
23
+ require_relative "arf/observer"
24
+ require_relative "arf/types"
25
+ require_relative "arf/proto"
26
+ require_relative "arf/wire"
27
+ require_relative "arf/status"
28
+ require_relative "arf/rpc"
29
+ require_relative "arf/context"
30
+ require_relative "arf/server"
31
+
32
+ module Arf
33
+ def self.configure
34
+ inst = Configuration.instance
35
+ yield inst if block_given?
36
+ nil
37
+ end
38
+
39
+ def self.configuration = Configuration.instance
40
+ def self.config = configuration
41
+ def self.logger = configuration.logger
42
+
43
+ def self.connect(host, port)
44
+ Reactor.connect(host, port, Wire::Client)
45
+ end
46
+ end
metadata ADDED
@@ -0,0 +1,195 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: arf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Vito Sartori
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-12-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: brotli
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.6.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.6.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: concurrent-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: logrb
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.5
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.5
55
+ - !ruby/object:Gem::Dependency
56
+ name: nio4r
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.7'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: zlib
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.2'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.2'
83
+ description: Opinionated RPC framework for inter-process, inter-application communication
84
+ email:
85
+ - hey@vito.io
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".ruby-version"
91
+ - LICENSE.txt
92
+ - Rakefile
93
+ - lib/arf.rb
94
+ - lib/arf/configuration.rb
95
+ - lib/arf/context.rb
96
+ - lib/arf/errors.rb
97
+ - lib/arf/io/buffer.rb
98
+ - lib/arf/io/compression.rb
99
+ - lib/arf/io/limit_reader.rb
100
+ - lib/arf/observer.rb
101
+ - lib/arf/proto.rb
102
+ - lib/arf/proto/array.rb
103
+ - lib/arf/proto/boolean.rb
104
+ - lib/arf/proto/bytes.rb
105
+ - lib/arf/proto/decoder.rb
106
+ - lib/arf/proto/encoder.rb
107
+ - lib/arf/proto/float.rb
108
+ - lib/arf/proto/map.rb
109
+ - lib/arf/proto/registry.rb
110
+ - lib/arf/proto/scalar.rb
111
+ - lib/arf/proto/string.rb
112
+ - lib/arf/proto/struct.rb
113
+ - lib/arf/proto/types.rb
114
+ - lib/arf/proto/union.rb
115
+ - lib/arf/reactor.rb
116
+ - lib/arf/rpc.rb
117
+ - lib/arf/rpc/base_message.rb
118
+ - lib/arf/rpc/client_base.rb
119
+ - lib/arf/rpc/end_stream.rb
120
+ - lib/arf/rpc/enum.rb
121
+ - lib/arf/rpc/message_kind.rb
122
+ - lib/arf/rpc/metadata.rb
123
+ - lib/arf/rpc/method_meta.rb
124
+ - lib/arf/rpc/request.rb
125
+ - lib/arf/rpc/responder.rb
126
+ - lib/arf/rpc/response.rb
127
+ - lib/arf/rpc/service_base.rb
128
+ - lib/arf/rpc/start_stream.rb
129
+ - lib/arf/rpc/stream_error.rb
130
+ - lib/arf/rpc/stream_item.rb
131
+ - lib/arf/rpc/stream_metadata.rb
132
+ - lib/arf/rpc/struct.rb
133
+ - lib/arf/server.rb
134
+ - lib/arf/status.rb
135
+ - lib/arf/types.rb
136
+ - lib/arf/types/array_type.rb
137
+ - lib/arf/types/base_type.rb
138
+ - lib/arf/types/coercion.rb
139
+ - lib/arf/types/in_out_stream.rb
140
+ - lib/arf/types/input_stream.rb
141
+ - lib/arf/types/map_type.rb
142
+ - lib/arf/types/mixin.rb
143
+ - lib/arf/types/output_stream.rb
144
+ - lib/arf/types/streamer.rb
145
+ - lib/arf/version.rb
146
+ - lib/arf/wire.rb
147
+ - lib/arf/wire/base_connection.rb
148
+ - lib/arf/wire/client.rb
149
+ - lib/arf/wire/encoding.rb
150
+ - lib/arf/wire/error_code.rb
151
+ - lib/arf/wire/errors.rb
152
+ - lib/arf/wire/frame.rb
153
+ - lib/arf/wire/frame_kind.rb
154
+ - lib/arf/wire/frame_reader.rb
155
+ - lib/arf/wire/frames.rb
156
+ - lib/arf/wire/frames/base_frame.rb
157
+ - lib/arf/wire/frames/configuration_frame.rb
158
+ - lib/arf/wire/frames/data_frame.rb
159
+ - lib/arf/wire/frames/go_away_frame.rb
160
+ - lib/arf/wire/frames/make_stream_frame.rb
161
+ - lib/arf/wire/frames/ping_frame.rb
162
+ - lib/arf/wire/frames/reset_stream_frame.rb
163
+ - lib/arf/wire/server.rb
164
+ - lib/arf/wire/server/peer.rb
165
+ - lib/arf/wire/stream.rb
166
+ - lib/arf/wire/stream/state.rb
167
+ - lib/arf/wire/wait_signal.rb
168
+ homepage: https://github.com/arf-rpc/arf-ruby
169
+ licenses:
170
+ - MIT
171
+ metadata:
172
+ allowed_push_host: https://rubygems.org
173
+ homepage_uri: https://github.com/arf-rpc/arf-ruby
174
+ changelog_uri: https://github.com/arf-rpc/arf-ruby/blob/master/CHANGELOG.md
175
+ rubygems_mfa_required: 'true'
176
+ post_install_message:
177
+ rdoc_options: []
178
+ require_paths:
179
+ - lib
180
+ required_ruby_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: '3.2'
185
+ required_rubygems_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - ">="
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ requirements: []
191
+ rubygems_version: 3.5.16
192
+ signing_key:
193
+ specification_version: 4
194
+ summary: arf stands for Another RPC Framework
195
+ test_files: []