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