rakie 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|