rakie 0.0.2
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 +7 -0
- data/Rakefile +0 -0
- data/lib/rakie/channel.rb +121 -0
- data/lib/rakie/event.rb +170 -0
- data/lib/rakie/simple_server.rb +149 -0
- data/lib/rakie/tcp_channel.rb +10 -0
- data/lib/rakie/tcp_server_channel.rb +52 -0
- data/lib/rakie.rb +10 -0
- data/test/test_rakie.rb +5 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 95d75f7ea14d2462c94b21bd025f17e5150075e295dd1dc9f927efb08826c424
|
4
|
+
data.tar.gz: 2642f719d6ae1427e99efc89b3d841fe7c7471f5cfd2da0597ad4df89d347b0e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ae10ff4d934dac0f08a066d2809930132b736e4cb4bda7f7cf25f30cc48f7554b4b474e8ee7cbb7fcd57b7b4e75157d9a592ff9a8351f3d9fbee431b4006e944
|
7
|
+
data.tar.gz: 287525054ef601031d860c7a8b75b1985e91d7430cee7b489b7fb726c06cbe15223c3ebd63cad3fbdf590793d3cb343dbfc0a6890cba89a9cbf6b632541ab6a2
|
data/Rakefile
ADDED
File without changes
|
@@ -0,0 +1,121 @@
|
|
1
|
+
module Rakie
|
2
|
+
class Channel
|
3
|
+
attr_accessor :delegate
|
4
|
+
|
5
|
+
def initialize(io, delegate=nil)
|
6
|
+
@io = io
|
7
|
+
@read_buffer = String.new
|
8
|
+
@write_buffer = String.new
|
9
|
+
@delegate = delegate
|
10
|
+
Event.push(io, self, Event::READ_EVENT)
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_read(io)
|
14
|
+
begin
|
15
|
+
loop do
|
16
|
+
@read_buffer << io.read_nonblock(4096)
|
17
|
+
end
|
18
|
+
|
19
|
+
rescue IO::EAGAINWaitReadable
|
20
|
+
puts("Channel read finished")
|
21
|
+
|
22
|
+
rescue
|
23
|
+
# Process the last message on exception
|
24
|
+
if @delegate != nil
|
25
|
+
@delegate.on_recv(self, @read_buffer)
|
26
|
+
@read_buffer = String.new # Reset buffer
|
27
|
+
end
|
28
|
+
|
29
|
+
puts("Channel error #{io}")
|
30
|
+
return Event::HANDLE_FAILED
|
31
|
+
end
|
32
|
+
|
33
|
+
puts("Channel has delegate?: #{@delegate}")
|
34
|
+
if @delegate != nil
|
35
|
+
len = @delegate.on_recv(self, @read_buffer)
|
36
|
+
|
37
|
+
if len > @read_buffer.length
|
38
|
+
len = @read_buffer.length
|
39
|
+
end
|
40
|
+
|
41
|
+
@read_buffer = @read_buffer[len .. -1]
|
42
|
+
puts("Channel handle on_recv")
|
43
|
+
end
|
44
|
+
|
45
|
+
return Event::HANDLE_CONTINUED
|
46
|
+
end
|
47
|
+
|
48
|
+
def on_write(io)
|
49
|
+
begin
|
50
|
+
while @write_buffer.length > 0
|
51
|
+
len = io.write_nonblock(@write_buffer)
|
52
|
+
@write_buffer = @write_buffer[len .. -1]
|
53
|
+
end
|
54
|
+
|
55
|
+
puts("Channel write finished")
|
56
|
+
|
57
|
+
rescue IO::EAGAINWaitWritable
|
58
|
+
puts("Channel write continue")
|
59
|
+
return Event::HANDLE_CONTINUED
|
60
|
+
|
61
|
+
rescue
|
62
|
+
puts("Channel close #{io}")
|
63
|
+
return Event::HANDLE_FAILED
|
64
|
+
end
|
65
|
+
|
66
|
+
return Event::HANDLE_FINISHED
|
67
|
+
end
|
68
|
+
|
69
|
+
def on_close(io)
|
70
|
+
begin
|
71
|
+
io.close
|
72
|
+
|
73
|
+
rescue
|
74
|
+
puts("Channel is already closed")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def read(size)
|
79
|
+
if self.eof?
|
80
|
+
return ""
|
81
|
+
end
|
82
|
+
|
83
|
+
if size > data.length
|
84
|
+
size = data.length
|
85
|
+
end
|
86
|
+
|
87
|
+
data = @read_buffer[0 .. (size - 1)]
|
88
|
+
@read_buffer = @read_buffer[size .. -1]
|
89
|
+
|
90
|
+
return data
|
91
|
+
end
|
92
|
+
|
93
|
+
def write(data)
|
94
|
+
if @io.closed?
|
95
|
+
return -1
|
96
|
+
end
|
97
|
+
|
98
|
+
@write_buffer << data
|
99
|
+
Event.modify(@io, self, Event::READ_EVENT | Event::WRITE_EVENT)
|
100
|
+
|
101
|
+
return 0
|
102
|
+
end
|
103
|
+
|
104
|
+
def close
|
105
|
+
if @io.closed?
|
106
|
+
return nil
|
107
|
+
end
|
108
|
+
|
109
|
+
Event.delete(@io)
|
110
|
+
return nil
|
111
|
+
end
|
112
|
+
|
113
|
+
def eof?
|
114
|
+
@read_buffer.empty?
|
115
|
+
end
|
116
|
+
|
117
|
+
def closed?
|
118
|
+
@io.closed?
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/lib/rakie/event.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
module Rakie
|
2
|
+
class Event
|
3
|
+
@instance = nil
|
4
|
+
|
5
|
+
READ_EVENT = 1
|
6
|
+
WRITE_EVENT = 2
|
7
|
+
|
8
|
+
HANDLE_FAILED = -1
|
9
|
+
HANDLE_CONTINUED = 0
|
10
|
+
HANDLE_FINISHED = 1
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@wait_ios = []
|
14
|
+
@lock = Mutex.new
|
15
|
+
@signal_in, @signal_out = IO.pipe
|
16
|
+
@ios = {
|
17
|
+
@signal_in => READ_EVENT
|
18
|
+
}
|
19
|
+
@handlers = {}
|
20
|
+
@run_loop = Thread.new do
|
21
|
+
self.run_loop
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def process_signal(io)
|
26
|
+
signal = io.read(1)
|
27
|
+
puts("Event handling #{signal}")
|
28
|
+
|
29
|
+
if signal == 'a'
|
30
|
+
new_io, new_handler, new_event = @wait_ios.shift
|
31
|
+
@ios[new_io] = new_event
|
32
|
+
@handlers[new_io] = new_handler
|
33
|
+
puts("Event add all #{new_io} to #{new_event}")
|
34
|
+
|
35
|
+
elsif signal == 'd'
|
36
|
+
new_io, = @wait_ios.shift
|
37
|
+
handler = @handlers[new_io]
|
38
|
+
|
39
|
+
if handler != nil
|
40
|
+
handler.on_close(new_io)
|
41
|
+
puts("Event close #{new_io}")
|
42
|
+
end
|
43
|
+
|
44
|
+
@ios.delete(new_io)
|
45
|
+
@handlers.delete(new_io)
|
46
|
+
|
47
|
+
puts("Event remove all #{new_io}")
|
48
|
+
|
49
|
+
elsif signal == 'm'
|
50
|
+
new_io, new_handler, new_event = @wait_ios.shift
|
51
|
+
@ios[new_io] = new_event
|
52
|
+
@handlers[new_io] = new_handler
|
53
|
+
puts("Event modify all #{new_io} to #{new_event}")
|
54
|
+
|
55
|
+
elsif signal == 'q'
|
56
|
+
return 1
|
57
|
+
end
|
58
|
+
|
59
|
+
return 0
|
60
|
+
end
|
61
|
+
|
62
|
+
def run_loop
|
63
|
+
loop do
|
64
|
+
read_ios = @ios.select {|k, v| v & READ_EVENT > 0}
|
65
|
+
write_ios = @ios.select {|k, v| v & WRITE_EVENT > 0}
|
66
|
+
|
67
|
+
read_ready, write_ready = IO.select(read_ios.keys, write_ios.keys, [], 5)
|
68
|
+
|
69
|
+
if read_ready != nil
|
70
|
+
read_ready.each do |io|
|
71
|
+
if io == @signal_in
|
72
|
+
@lock.lock
|
73
|
+
|
74
|
+
if self.process_signal(io) != 0
|
75
|
+
@lock.unlock
|
76
|
+
return
|
77
|
+
end
|
78
|
+
|
79
|
+
@lock.unlock
|
80
|
+
next
|
81
|
+
end
|
82
|
+
|
83
|
+
handler = @handlers[io]
|
84
|
+
|
85
|
+
if handler == nil
|
86
|
+
next
|
87
|
+
end
|
88
|
+
|
89
|
+
result = handler.on_read(io)
|
90
|
+
|
91
|
+
if result == HANDLE_FINISHED
|
92
|
+
@ios[io] = @ios[io] & ~READ_EVENT
|
93
|
+
puts("Event remove read #{io}")
|
94
|
+
|
95
|
+
elsif result == HANDLE_FAILED
|
96
|
+
handler.on_close(io)
|
97
|
+
puts("Event close #{io}")
|
98
|
+
|
99
|
+
@ios.delete(io)
|
100
|
+
@handlers.delete(io)
|
101
|
+
puts("Event remove all #{io}")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
if write_ready != nil
|
107
|
+
write_ready.each do |io|
|
108
|
+
handler = @handlers[io]
|
109
|
+
|
110
|
+
if handler == nil
|
111
|
+
next
|
112
|
+
end
|
113
|
+
|
114
|
+
result = handler.on_write(io)
|
115
|
+
|
116
|
+
if result == HANDLE_FINISHED
|
117
|
+
@ios[io] = @ios[io] & ~WRITE_EVENT
|
118
|
+
puts("Event remove write #{io}")
|
119
|
+
|
120
|
+
elsif result == HANDLE_FAILED
|
121
|
+
handler.on_close(io)
|
122
|
+
puts("Event close #{io}")
|
123
|
+
|
124
|
+
@ios.delete(io)
|
125
|
+
@handlers.delete(io)
|
126
|
+
puts("Event remove all #{io}")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def push(io, handler, event)
|
134
|
+
@lock.lock
|
135
|
+
@wait_ios.push([io, handler, event])
|
136
|
+
@signal_out.write('a')
|
137
|
+
@lock.unlock
|
138
|
+
end
|
139
|
+
|
140
|
+
def delete(io)
|
141
|
+
@lock.lock
|
142
|
+
@wait_ios.push([io, nil, nil])
|
143
|
+
@signal_out.write('d')
|
144
|
+
@lock.unlock
|
145
|
+
end
|
146
|
+
|
147
|
+
def modify(io, handler, event)
|
148
|
+
@lock.lock
|
149
|
+
@wait_ios.push([io, handler, event])
|
150
|
+
@signal_out.write('m')
|
151
|
+
@lock.unlock
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.instance
|
155
|
+
@instance ||= Event.new
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.push(io, listener, type)
|
159
|
+
self.instance.push(io, listener, type)
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.delete(io)
|
163
|
+
self.instance.delete(io)
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.modify(io, listener, type)
|
167
|
+
self.instance.modify(io, listener, type)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module Rakie
|
2
|
+
class SimpleServer
|
3
|
+
PARSE_ERROR = -1
|
4
|
+
PARSE_OK = 0
|
5
|
+
PARSE_PENDING = 1
|
6
|
+
PARSE_COMPLETE = 2
|
7
|
+
|
8
|
+
PARSE_TYPE = 0
|
9
|
+
PARSE_LEN = 1
|
10
|
+
PARSE_ENTITY = 2
|
11
|
+
|
12
|
+
def initialize(delegate=nil)
|
13
|
+
@channel = TCPServerChannel.new('127.0.0.1', 10086, self)
|
14
|
+
@clients = {}
|
15
|
+
@delegate = delegate
|
16
|
+
end
|
17
|
+
|
18
|
+
def on_accept(channel)
|
19
|
+
channel.delegate = self
|
20
|
+
@clients[channel] = {
|
21
|
+
:parse_status => PARSE_TYPE,
|
22
|
+
:parse_offset => 0,
|
23
|
+
:request => {
|
24
|
+
:type => 0,
|
25
|
+
:len => 0,
|
26
|
+
:entity => ""
|
27
|
+
},
|
28
|
+
:response => {
|
29
|
+
:type => 0,
|
30
|
+
:len => 0,
|
31
|
+
:entity => ""
|
32
|
+
}
|
33
|
+
}
|
34
|
+
puts("SimpleServer accept client: #{channel}")
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_data_type(client, data)
|
38
|
+
if data.length >= 1
|
39
|
+
type = data[0].ord
|
40
|
+
client[:request][:type] = type
|
41
|
+
client[:parse_status] = PARSE_LEN
|
42
|
+
client[:parse_offset] += 1
|
43
|
+
|
44
|
+
puts("SimpleServer parse data type ok")
|
45
|
+
return PARSE_OK
|
46
|
+
end
|
47
|
+
|
48
|
+
return PARSE_PENDING
|
49
|
+
end
|
50
|
+
|
51
|
+
def parse_data_len(client, data)
|
52
|
+
offset = client[:parse_offset]
|
53
|
+
|
54
|
+
if data.length >= 4 + offset
|
55
|
+
len = data[offset .. (4 + offset - 1)]
|
56
|
+
len = len.unpack('l')[0]
|
57
|
+
|
58
|
+
if len == nil
|
59
|
+
return PARSE_ERROR
|
60
|
+
end
|
61
|
+
|
62
|
+
client[:request][:len] = len
|
63
|
+
client[:parse_status] = PARSE_ENTITY
|
64
|
+
client[:parse_offset] = offset + 4
|
65
|
+
|
66
|
+
puts("SimpleServer parse data len ok")
|
67
|
+
return PARSE_OK
|
68
|
+
end
|
69
|
+
|
70
|
+
return PARSE_PENDING
|
71
|
+
end
|
72
|
+
|
73
|
+
def parse_data_entity(client, data)
|
74
|
+
len = client[:request][:len]
|
75
|
+
offset = client[:parse_offset]
|
76
|
+
|
77
|
+
if data.length >= len + offset
|
78
|
+
client[:request][:entity] = data[offset .. (offset + len - 1)]
|
79
|
+
client[:parse_status] = PARSE_TYPE
|
80
|
+
client[:parse_offset] = offset + len
|
81
|
+
|
82
|
+
puts("SimpleServer parse data entity ok")
|
83
|
+
return PARSE_COMPLETE
|
84
|
+
end
|
85
|
+
|
86
|
+
return PARSE_PENDING
|
87
|
+
end
|
88
|
+
|
89
|
+
def parse_data(client, data)
|
90
|
+
result = PARSE_OK
|
91
|
+
|
92
|
+
while result == PARSE_OK
|
93
|
+
current_status = client[:parse_status]
|
94
|
+
|
95
|
+
case current_status
|
96
|
+
when PARSE_TYPE
|
97
|
+
result = self.parse_data_type(client, data)
|
98
|
+
|
99
|
+
when PARSE_LEN
|
100
|
+
result = self.parse_data_len(client, data)
|
101
|
+
|
102
|
+
when PARSE_ENTITY
|
103
|
+
result = self.parse_data_entity(client, data)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
puts("SimpleServer parse data result #{result}")
|
108
|
+
|
109
|
+
return result
|
110
|
+
end
|
111
|
+
|
112
|
+
def pack_data(response)
|
113
|
+
data = ""
|
114
|
+
data += [response[:type]].pack('c')
|
115
|
+
data += [response[:len]].pack('l')
|
116
|
+
data += response[:entity]
|
117
|
+
end
|
118
|
+
|
119
|
+
def on_recv(channel, data)
|
120
|
+
puts("SimpleServer recv: #{data}")
|
121
|
+
client = @clients[channel]
|
122
|
+
client[:parse_offset] = 0
|
123
|
+
result = self.parse_data(client, data)
|
124
|
+
|
125
|
+
pp client
|
126
|
+
|
127
|
+
if result == PARSE_COMPLETE
|
128
|
+
if @delegate != nil
|
129
|
+
@delegate.handle(client[:request], client[:response])
|
130
|
+
|
131
|
+
else
|
132
|
+
client[:response] = client[:request]
|
133
|
+
end
|
134
|
+
|
135
|
+
channel.write(self.pack_data(client[:response])) # Response data
|
136
|
+
|
137
|
+
elsif result == PARSE_ERROR
|
138
|
+
channel.close
|
139
|
+
@clients.delete(channel)
|
140
|
+
puts("SimpleServer: Illegal request")
|
141
|
+
return client[:parse_offset]
|
142
|
+
end
|
143
|
+
|
144
|
+
return client[:parse_offset]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
require "pp"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Rakie
|
2
|
+
class TCPServerChannel < Channel
|
3
|
+
def initialize(ip, port=nil, delegate=nil)
|
4
|
+
io = nil
|
5
|
+
|
6
|
+
if port == nil
|
7
|
+
port = ip
|
8
|
+
io = TCPServer.new(ip)
|
9
|
+
|
10
|
+
else
|
11
|
+
io = TCPServer.new(ip, port)
|
12
|
+
end
|
13
|
+
|
14
|
+
@clients = []
|
15
|
+
|
16
|
+
super(io, delegate)
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_read(io)
|
20
|
+
begin
|
21
|
+
client_io, = io.accept_nonblock
|
22
|
+
channel = Channel.new(client_io)
|
23
|
+
|
24
|
+
if @delegate != nil
|
25
|
+
puts("TCPServerChannel has delegate")
|
26
|
+
@delegate.on_accept(channel)
|
27
|
+
|
28
|
+
else
|
29
|
+
puts("TCPServerChannel no delegate")
|
30
|
+
@clients << channel
|
31
|
+
end
|
32
|
+
|
33
|
+
puts("TCPServerChannel accept #{channel}")
|
34
|
+
|
35
|
+
rescue IO::EAGAINWaitReadable
|
36
|
+
puts("TCPServerChannel accept wait")
|
37
|
+
|
38
|
+
rescue
|
39
|
+
puts("TCPServerChannel Accept failed #{io}")
|
40
|
+
return Event::HANDLE_FAILED
|
41
|
+
end
|
42
|
+
|
43
|
+
return Event::HANDLE_CONTINUED
|
44
|
+
end
|
45
|
+
|
46
|
+
def accept
|
47
|
+
@clients.shift
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
require "socket"
|
data/lib/rakie.rb
ADDED
data/test/test_rakie.rb
ADDED
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rakie
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jakit Liang
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-03-29 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Rakie is lucky and lucky
|
14
|
+
email: jakitliang@163.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- Rakefile
|
20
|
+
- lib/rakie.rb
|
21
|
+
- lib/rakie/channel.rb
|
22
|
+
- lib/rakie/event.rb
|
23
|
+
- lib/rakie/simple_server.rb
|
24
|
+
- lib/rakie/tcp_channel.rb
|
25
|
+
- lib/rakie/tcp_server_channel.rb
|
26
|
+
- test/test_rakie.rb
|
27
|
+
homepage: https://github.com/Jakitto/rakie
|
28
|
+
licenses:
|
29
|
+
- BSD-2-Clause-Patent
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubygems_version: 3.0.9
|
47
|
+
signing_key:
|
48
|
+
specification_version: 4
|
49
|
+
summary: Rakie!
|
50
|
+
test_files:
|
51
|
+
- test/test_rakie.rb
|