arf 0.1.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.
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: []