rakie 0.0.2 → 0.0.8
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/lib/rakie.rb +15 -1
- data/lib/rakie/channel.rb +57 -12
- data/lib/rakie/event.rb +70 -35
- data/lib/rakie/http.rb +5 -0
- data/lib/rakie/http_proto.rb +197 -0
- data/lib/rakie/http_server.rb +134 -0
- data/lib/rakie/log.rb +96 -0
- data/lib/rakie/proto.rb +63 -0
- data/lib/rakie/simple_server.rb +7 -11
- data/lib/rakie/tcp_channel.rb +19 -3
- data/lib/rakie/tcp_server_channel.rb +32 -16
- data/lib/rakie/version.rb +11 -0
- data/lib/rakie/websocket.rb +138 -0
- data/lib/rakie/websocket_proto.rb +286 -0
- data/lib/rakie/websocket_server.rb +89 -0
- data/test/test_rakie.rb +8 -3
- metadata +13 -4
@@ -0,0 +1,134 @@
|
|
1
|
+
module Rakie
|
2
|
+
class HttpServer
|
3
|
+
class Session
|
4
|
+
# @return [HttpRequest]
|
5
|
+
attr_accessor :request
|
6
|
+
|
7
|
+
# @type [Array<HttpResponse>]
|
8
|
+
attr_accessor :responses
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@request = HttpRequest.new
|
12
|
+
@responses = []
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :channel, :opt, :host, :port
|
17
|
+
|
18
|
+
def initialize(host: '127.0.0.1', port: 10086, delegate: nil)
|
19
|
+
@host = host
|
20
|
+
@port = port
|
21
|
+
|
22
|
+
@channel = TCPServerChannel.new(host, port, self)
|
23
|
+
|
24
|
+
# @type [Hash{Channel=>Session}]
|
25
|
+
@sessions = {}
|
26
|
+
@delegate = delegate
|
27
|
+
@opt = {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def on_accept(channel)
|
31
|
+
channel.delegate = self
|
32
|
+
@sessions[channel] = Session.new
|
33
|
+
Log.debug("Rakie::HTTPServer accept client: #{channel}")
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_recv(channel, data)
|
37
|
+
# Log.debug("Rakie::HTTPServer recv: #{data}")
|
38
|
+
session = @sessions[channel]
|
39
|
+
|
40
|
+
if session == nil
|
41
|
+
return 0
|
42
|
+
end
|
43
|
+
|
44
|
+
# @type [HttpRequest] request
|
45
|
+
request = session.request
|
46
|
+
|
47
|
+
if request.parse_status == ParseStatus::COMPLETE
|
48
|
+
request = HttpRequest.new
|
49
|
+
session.request = request
|
50
|
+
end
|
51
|
+
|
52
|
+
len = request.parse(data)
|
53
|
+
|
54
|
+
Log.debug("Rakie::HttpServer receive request: #{request.to_s}")
|
55
|
+
|
56
|
+
if request.parse_status == ParseStatus::COMPLETE
|
57
|
+
response = HttpResponse.new
|
58
|
+
|
59
|
+
if upgrade = request.headers["upgrade"]
|
60
|
+
if websocket_delegate = @opt[:websocket_delegate]
|
61
|
+
websocket_delegate.upgrade(request, response)
|
62
|
+
Log.debug("Rakie::HttpServer upgrade protocol")
|
63
|
+
end
|
64
|
+
|
65
|
+
elsif @delegate != nil
|
66
|
+
@delegate.handle(request, response)
|
67
|
+
|
68
|
+
else
|
69
|
+
response.headers["content-type"] = HttpMIME::HTML
|
70
|
+
response.content = "<html><body><h1>Rakie!</h1></body></html>"
|
71
|
+
end
|
72
|
+
|
73
|
+
if header_connection = request.headers["connection"]
|
74
|
+
response.headers["connection"] = header_connection
|
75
|
+
end
|
76
|
+
|
77
|
+
if response.content.length > 0
|
78
|
+
response.headers["content-length"] = response.content.length
|
79
|
+
end
|
80
|
+
|
81
|
+
response.headers["server"] = Rakie.full_version_s
|
82
|
+
session.responses << response
|
83
|
+
response_data = response.to_s
|
84
|
+
|
85
|
+
Log.debug("Rakie::HttpServer response: #{response_data}")
|
86
|
+
|
87
|
+
channel.write(response_data) # Response data
|
88
|
+
|
89
|
+
elsif request.parse_status == ParseStatus::ERROR
|
90
|
+
channel.close
|
91
|
+
@sessions.delete(channel)
|
92
|
+
|
93
|
+
Log.debug("Rakie::HttpServer: Illegal request")
|
94
|
+
return len
|
95
|
+
end
|
96
|
+
|
97
|
+
return len
|
98
|
+
end
|
99
|
+
|
100
|
+
def on_send(channel)
|
101
|
+
session = @sessions[channel]
|
102
|
+
# @type [HttpRequest]
|
103
|
+
last_response = session.responses.shift
|
104
|
+
|
105
|
+
if last_response
|
106
|
+
if connect_status = last_response.headers["connection"]
|
107
|
+
if connect_status.downcase == "close"
|
108
|
+
Log.debug("Rakie::HttpServer: send finish and close channel")
|
109
|
+
channel.close
|
110
|
+
@sessions.delete(channel)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
if upgrade = last_response.headers["upgrade"]
|
115
|
+
websocket_delegate = @opt[:websocket_delegate]
|
116
|
+
|
117
|
+
if websocket_delegate
|
118
|
+
websocket_delegate.on_accept(channel)
|
119
|
+
@sessions.delete(channel)
|
120
|
+
return
|
121
|
+
end
|
122
|
+
|
123
|
+
Log.debug("Rakie::HttpServer: no websocket delegate and close channel")
|
124
|
+
channel.close
|
125
|
+
@sessions.delete(channel)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def on_close(channel)
|
131
|
+
@sessions.delete(channel)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/lib/rakie/log.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
module Rakie
|
2
|
+
class Log
|
3
|
+
attr_accessor :out, :level
|
4
|
+
|
5
|
+
@instance = nil
|
6
|
+
|
7
|
+
LEVEL_INFO = 0
|
8
|
+
LEVEL_ERROR = 1
|
9
|
+
LEVEL_DEBUG = 2
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@level = Rakie.current_mode == Rakie::MODE_DEV ? LEVEL_DEBUG : LEVEL_ERROR
|
13
|
+
@out = STDOUT
|
14
|
+
end
|
15
|
+
|
16
|
+
def level_text(level=nil)
|
17
|
+
unless level
|
18
|
+
level = @level
|
19
|
+
end
|
20
|
+
|
21
|
+
case level
|
22
|
+
when LEVEL_INFO
|
23
|
+
return "INFO"
|
24
|
+
|
25
|
+
when LEVEL_ERROR
|
26
|
+
return "ERROR"
|
27
|
+
|
28
|
+
when LEVEL_DEBUG
|
29
|
+
return "DEBUG"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def level_info?
|
34
|
+
@level >= LEVEL_INFO
|
35
|
+
end
|
36
|
+
|
37
|
+
def level_error?
|
38
|
+
@level >= LEVEL_ERROR
|
39
|
+
end
|
40
|
+
|
41
|
+
def level_debug?
|
42
|
+
@level >= LEVEL_DEBUG
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.instance
|
46
|
+
@instance ||= Log.new
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.info(message, who=nil)
|
50
|
+
unless self.instance.level_info?
|
51
|
+
return
|
52
|
+
end
|
53
|
+
|
54
|
+
if who
|
55
|
+
message = "#{who}: #{message}"
|
56
|
+
end
|
57
|
+
|
58
|
+
level = self.instance.level_text(LEVEL_INFO)
|
59
|
+
self.instance.out.write("[#{Time.now.to_s}][#{level}] #{message}\n")
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.error(message, who=nil)
|
63
|
+
unless self.instance.level_error?
|
64
|
+
return
|
65
|
+
end
|
66
|
+
|
67
|
+
if who
|
68
|
+
message = "#{who}: #{message}"
|
69
|
+
end
|
70
|
+
|
71
|
+
level = self.instance.level_text(LEVEL_ERROR)
|
72
|
+
self.instance.out.write("[#{Time.now.to_s}][#{level}] #{message}\n")
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.debug(message, who=nil)
|
76
|
+
unless self.instance.level_debug?
|
77
|
+
return
|
78
|
+
end
|
79
|
+
|
80
|
+
if who
|
81
|
+
message = "#{who}: #{message}"
|
82
|
+
end
|
83
|
+
|
84
|
+
level = self.instance.level_text(LEVEL_DEBUG)
|
85
|
+
self.instance.out.print("[#{Time.now.to_s}][#{level}] #{message}\n")
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.level
|
89
|
+
self.instance.level
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.level=(level)
|
93
|
+
self.instance.level = level
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/rakie/proto.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
module Rakie
|
2
|
+
class ParseStatus
|
3
|
+
ERROR = -1
|
4
|
+
CONTINUE = 0
|
5
|
+
PENDING = 1
|
6
|
+
COMPLETE = 2
|
7
|
+
end
|
8
|
+
|
9
|
+
module Proto
|
10
|
+
PARSE_BEGIN = 0
|
11
|
+
|
12
|
+
# @return [Integer]
|
13
|
+
def parse_status
|
14
|
+
@parse_status ||= ParseStatus::CONTINUE
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Integer]
|
18
|
+
def parse_state
|
19
|
+
@parse_state ||= PARSE_BEGIN
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param [Integer] state
|
23
|
+
def parse_state=(state)
|
24
|
+
@parse_state = state
|
25
|
+
# puts("Set state: #{@parse_state}")
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [Integer]
|
29
|
+
def parse_offset
|
30
|
+
@parse_offset ||= 0
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param [Integer] offset
|
34
|
+
def parse_offset=(offset)
|
35
|
+
@parse_offset = offset
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param [String] source
|
39
|
+
def parse(source)
|
40
|
+
status = ParseStatus::CONTINUE
|
41
|
+
|
42
|
+
while status == ParseStatus::CONTINUE
|
43
|
+
status = self.deserialize(source)
|
44
|
+
end
|
45
|
+
|
46
|
+
if status == ParseStatus::PENDING
|
47
|
+
status = ParseStatus::CONTINUE
|
48
|
+
end
|
49
|
+
|
50
|
+
offset = @parse_offset
|
51
|
+
@parse_status = status
|
52
|
+
@parse_offset = 0
|
53
|
+
|
54
|
+
return offset
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param [Object] object
|
58
|
+
# @return [String]
|
59
|
+
def to_s
|
60
|
+
self.serialize
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/rakie/simple_server.rb
CHANGED
@@ -31,7 +31,7 @@ module Rakie
|
|
31
31
|
:entity => ""
|
32
32
|
}
|
33
33
|
}
|
34
|
-
|
34
|
+
Log.debug("SimpleServer accept client: #{channel}")
|
35
35
|
end
|
36
36
|
|
37
37
|
def parse_data_type(client, data)
|
@@ -41,7 +41,7 @@ module Rakie
|
|
41
41
|
client[:parse_status] = PARSE_LEN
|
42
42
|
client[:parse_offset] += 1
|
43
43
|
|
44
|
-
|
44
|
+
Log.debug("SimpleServer parse data type ok")
|
45
45
|
return PARSE_OK
|
46
46
|
end
|
47
47
|
|
@@ -63,7 +63,7 @@ module Rakie
|
|
63
63
|
client[:parse_status] = PARSE_ENTITY
|
64
64
|
client[:parse_offset] = offset + 4
|
65
65
|
|
66
|
-
|
66
|
+
Log.debug("SimpleServer parse data len ok")
|
67
67
|
return PARSE_OK
|
68
68
|
end
|
69
69
|
|
@@ -79,7 +79,7 @@ module Rakie
|
|
79
79
|
client[:parse_status] = PARSE_TYPE
|
80
80
|
client[:parse_offset] = offset + len
|
81
81
|
|
82
|
-
|
82
|
+
Log.debug("SimpleServer parse data entity ok")
|
83
83
|
return PARSE_COMPLETE
|
84
84
|
end
|
85
85
|
|
@@ -104,7 +104,7 @@ module Rakie
|
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
107
|
-
|
107
|
+
Log.debug("SimpleServer parse data result #{result}")
|
108
108
|
|
109
109
|
return result
|
110
110
|
end
|
@@ -117,13 +117,11 @@ module Rakie
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def on_recv(channel, data)
|
120
|
-
|
120
|
+
Log.debug("SimpleServer recv: #{data}")
|
121
121
|
client = @clients[channel]
|
122
122
|
client[:parse_offset] = 0
|
123
123
|
result = self.parse_data(client, data)
|
124
124
|
|
125
|
-
pp client
|
126
|
-
|
127
125
|
if result == PARSE_COMPLETE
|
128
126
|
if @delegate != nil
|
129
127
|
@delegate.handle(client[:request], client[:response])
|
@@ -137,7 +135,7 @@ module Rakie
|
|
137
135
|
elsif result == PARSE_ERROR
|
138
136
|
channel.close
|
139
137
|
@clients.delete(channel)
|
140
|
-
|
138
|
+
Log.debug("SimpleServer: Illegal request")
|
141
139
|
return client[:parse_offset]
|
142
140
|
end
|
143
141
|
|
@@ -145,5 +143,3 @@ module Rakie
|
|
145
143
|
end
|
146
144
|
end
|
147
145
|
end
|
148
|
-
|
149
|
-
require "pp"
|
data/lib/rakie/tcp_channel.rb
CHANGED
@@ -1,8 +1,24 @@
|
|
1
1
|
module Rakie
|
2
2
|
class TCPChannel < Channel
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
LOCAL_HOST = '127.0.0.1'
|
4
|
+
|
5
|
+
# @param host [String]
|
6
|
+
# @param port [Integer]
|
7
|
+
# @param delegate [Object]
|
8
|
+
# @param socket [Socket]
|
9
|
+
# @overload initialize(host, port, delegate)
|
10
|
+
# @overload initialize(host, port)
|
11
|
+
# @overload initialize(host, port, delegate, socket)
|
12
|
+
def initialize(host=LOCAL_HOST, port=3001, delegate=nil, socket=nil)
|
13
|
+
if socket == nil
|
14
|
+
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
|
15
|
+
socket.connect(Socket.pack_sockaddr_in(port, host))
|
16
|
+
end
|
17
|
+
|
18
|
+
@port = port
|
19
|
+
@host = host
|
20
|
+
|
21
|
+
super(socket, delegate)
|
6
22
|
end
|
7
23
|
end
|
8
24
|
end
|
@@ -1,42 +1,58 @@
|
|
1
1
|
module Rakie
|
2
|
-
class TCPServerChannel <
|
3
|
-
|
4
|
-
|
2
|
+
class TCPServerChannel < TCPChannel
|
3
|
+
# @param host [String]
|
4
|
+
# @param port [Integer]
|
5
|
+
# @param delegate [Object]
|
6
|
+
# @overload initialize(host, port, delegate)
|
7
|
+
# @overload initialize(host, port)
|
8
|
+
# @overload initialize(port)
|
9
|
+
def initialize(host=LOCAL_HOST, port=3001, delegate=nil)
|
10
|
+
socket = nil
|
5
11
|
|
6
12
|
if port == nil
|
7
|
-
port =
|
8
|
-
|
9
|
-
|
10
|
-
else
|
11
|
-
io = TCPServer.new(ip, port)
|
13
|
+
port = host
|
14
|
+
host = LOCAL_HOST
|
12
15
|
end
|
13
16
|
|
17
|
+
socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
|
18
|
+
socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
|
19
|
+
socket.bind(Socket.pack_sockaddr_in(port, host))
|
20
|
+
socket.listen(255)
|
21
|
+
|
14
22
|
@clients = []
|
15
23
|
|
16
|
-
super(
|
24
|
+
super(host, port, delegate, socket)
|
17
25
|
end
|
18
26
|
|
27
|
+
# @param io [Socket]
|
19
28
|
def on_read(io)
|
20
29
|
begin
|
21
|
-
|
22
|
-
|
30
|
+
ret = io.accept_nonblock
|
31
|
+
# @type client_io [Socket]
|
32
|
+
client_io = ret[0]
|
33
|
+
# @type client_info [Addrinfo]
|
34
|
+
client_info = ret[1]
|
35
|
+
client_name_info = client_info.getnameinfo
|
36
|
+
client_host = client_name_info[0]
|
37
|
+
client_port = client_name_info[1]
|
38
|
+
channel = TCPChannel.new(client_host, client_port, nil, client_io)
|
23
39
|
|
24
40
|
if @delegate != nil
|
25
|
-
|
41
|
+
Log.debug("TCPServerChannel has delegate")
|
26
42
|
@delegate.on_accept(channel)
|
27
43
|
|
28
44
|
else
|
29
|
-
|
45
|
+
Log.debug("TCPServerChannel no delegate")
|
30
46
|
@clients << channel
|
31
47
|
end
|
32
48
|
|
33
|
-
|
49
|
+
Log.debug("TCPServerChannel accept #{channel}")
|
34
50
|
|
35
51
|
rescue IO::EAGAINWaitReadable
|
36
|
-
|
52
|
+
Log.debug("TCPServerChannel accept wait")
|
37
53
|
|
38
54
|
rescue
|
39
|
-
|
55
|
+
Log.debug("TCPServerChannel Accept failed #{io}")
|
40
56
|
return Event::HANDLE_FAILED
|
41
57
|
end
|
42
58
|
|