bixby-common 0.3.16 → 0.4.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.
- checksums.yaml +7 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +55 -18
- data/Rakefile +1 -2
- data/VERSION +1 -1
- data/bixby-common.gemspec +21 -4
- data/lib/bixby-common/api/api_channel.rb +20 -0
- data/lib/bixby-common/api/encrypted_json_request.rb +19 -0
- data/lib/bixby-common/api/http_channel.rb +72 -0
- data/lib/bixby-common/api/json_request.rb +4 -0
- data/lib/bixby-common/api/json_response.rb +4 -0
- data/lib/bixby-common/api/rpc_handler.rb +35 -0
- data/lib/bixby-common/api/signed_json_request.rb +38 -0
- data/lib/bixby-common/command_spec.rb +1 -1
- data/lib/bixby-common/util/log.rb +21 -1
- data/lib/bixby-common/websocket/api_channel.rb +114 -0
- data/lib/bixby-common/websocket/async_response.rb +50 -0
- data/lib/bixby-common/websocket/client.rb +117 -0
- data/lib/bixby-common/websocket/message.rb +48 -0
- data/lib/bixby-common/websocket/request.rb +24 -0
- data/lib/bixby-common/websocket/response.rb +24 -0
- data/lib/bixby-common.rb +14 -0
- metadata +109 -121
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 53b5ec30f44a5f248d360a13d02bc46881e64f03
|
|
4
|
+
data.tar.gz: 4ad3d8400f6390ce4630a502e15e4fc9ca5d4507
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: db1b6968efb742cf556c6cfdeb4a0836a05869d5088abc126c5360d2e8d8494a209bd261d9bac3b5fdfb18fee17ce775b7d123bdd7a02149bd037970877726ef
|
|
7
|
+
data.tar.gz: 0ca4ee9520635bc97adea27f4c293b4a4797958a296eaf87d3d9d016618ff43c5db197522e99baf506cec46861001f4f5ec1233cc42787c9d79407084024fb2b
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
GIT
|
|
2
|
+
remote: https://github.com/chetan/api_auth.git
|
|
3
|
+
revision: 6d9351de901a51d6a386d547a8d32e23c4314550
|
|
4
|
+
branch: bixby
|
|
5
|
+
specs:
|
|
6
|
+
api-auth (1.0.3)
|
|
7
|
+
|
|
1
8
|
GIT
|
|
2
9
|
remote: https://github.com/chetan/httpi.git
|
|
3
10
|
revision: f6e49303fee6778c714bcc556fa5f9247bc3a3f3
|
|
@@ -8,12 +15,16 @@ GIT
|
|
|
8
15
|
|
|
9
16
|
GIT
|
|
10
17
|
remote: https://github.com/chetan/jeweler.git
|
|
11
|
-
revision:
|
|
18
|
+
revision: 9b8b2376c79299b823a5e9aafae3d647df943b6f
|
|
12
19
|
branch: bixby
|
|
13
20
|
specs:
|
|
14
|
-
jeweler (1.8.
|
|
21
|
+
jeweler (1.8.7)
|
|
22
|
+
builder
|
|
15
23
|
bundler (~> 1.0)
|
|
16
24
|
git (>= 1.2.5)
|
|
25
|
+
github_api (= 0.10.1)
|
|
26
|
+
highline (>= 1.6.15)
|
|
27
|
+
nokogiri (= 1.5.10)
|
|
17
28
|
rake
|
|
18
29
|
rdoc
|
|
19
30
|
|
|
@@ -28,14 +39,14 @@ GIT
|
|
|
28
39
|
|
|
29
40
|
GIT
|
|
30
41
|
remote: https://github.com/chetan/test_guard.git
|
|
31
|
-
revision:
|
|
42
|
+
revision: 7d069b2d7e46fcbecd7a52966fda7d2d1945e2c9
|
|
32
43
|
specs:
|
|
33
|
-
test_guard (0.2.
|
|
44
|
+
test_guard (0.2.1)
|
|
34
45
|
awesome_print
|
|
35
46
|
debugger
|
|
36
47
|
debugger-pry
|
|
37
48
|
growl
|
|
38
|
-
|
|
49
|
+
listen
|
|
39
50
|
simplecov
|
|
40
51
|
simplecov-console
|
|
41
52
|
single_test
|
|
@@ -48,6 +59,7 @@ GEM
|
|
|
48
59
|
ansi (1.4.3)
|
|
49
60
|
awesome_print (1.1.0)
|
|
50
61
|
bouncy-castle-java (1.5.0147)
|
|
62
|
+
builder (3.2.2)
|
|
51
63
|
coderay (1.0.9)
|
|
52
64
|
colorize (0.5.8)
|
|
53
65
|
columnize (0.3.6)
|
|
@@ -63,24 +75,36 @@ GEM
|
|
|
63
75
|
debugger (~> 1)
|
|
64
76
|
pry (>= 0.9.9)
|
|
65
77
|
debugger-ruby_core_source (1.2.3)
|
|
78
|
+
eventmachine (1.0.3)
|
|
79
|
+
eventmachine (1.0.3-java)
|
|
80
|
+
faraday (0.8.8)
|
|
81
|
+
multipart-post (~> 1.2.0)
|
|
82
|
+
faye-websocket (0.6.3)
|
|
83
|
+
eventmachine (>= 0.12.0)
|
|
84
|
+
websocket-driver (>= 0.2.0)
|
|
66
85
|
ffi (1.9.0)
|
|
67
86
|
ffi (1.9.0-java)
|
|
68
|
-
|
|
69
|
-
|
|
87
|
+
git (1.2.6)
|
|
88
|
+
github_api (0.10.1)
|
|
89
|
+
addressable
|
|
90
|
+
faraday (~> 0.8.1)
|
|
91
|
+
hashie (>= 1.2)
|
|
92
|
+
multi_json (~> 1.4)
|
|
93
|
+
nokogiri (~> 1.5.2)
|
|
94
|
+
oauth2
|
|
70
95
|
growl (1.0.3)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
listen (>= 1.0.0)
|
|
74
|
-
lumberjack (>= 1.0.2)
|
|
75
|
-
pry (>= 0.9.10)
|
|
76
|
-
thor (>= 0.14.6)
|
|
96
|
+
hashie (2.0.5)
|
|
97
|
+
highline (1.6.19)
|
|
77
98
|
hirb (0.7.1)
|
|
99
|
+
httpauth (0.2.0)
|
|
78
100
|
httpclient (2.3.4.1)
|
|
79
101
|
jruby-openssl (0.8.8)
|
|
80
102
|
bouncy-castle-java (>= 1.5.0147)
|
|
81
103
|
json (1.8.0)
|
|
82
104
|
json (1.8.0-java)
|
|
83
|
-
|
|
105
|
+
jwt (0.1.8)
|
|
106
|
+
multi_json (>= 1.5)
|
|
107
|
+
listen (1.3.0)
|
|
84
108
|
rb-fsevent (>= 0.9.3)
|
|
85
109
|
rb-inotify (>= 0.9)
|
|
86
110
|
rb-kqueue (>= 0.2)
|
|
@@ -88,13 +112,23 @@ GEM
|
|
|
88
112
|
logging (1.8.1)
|
|
89
113
|
little-plugger (>= 1.1.3)
|
|
90
114
|
multi_json (>= 1.3.6)
|
|
91
|
-
lumberjack (1.0.4)
|
|
92
115
|
metaclass (0.0.1)
|
|
93
116
|
method_source (0.8.2)
|
|
94
117
|
minitest (4.7.5)
|
|
95
118
|
mocha (0.14.0)
|
|
96
119
|
metaclass (~> 0.0.1)
|
|
97
120
|
multi_json (1.7.9)
|
|
121
|
+
multi_xml (0.5.5)
|
|
122
|
+
multipart-post (1.2.0)
|
|
123
|
+
nokogiri (1.5.10)
|
|
124
|
+
nokogiri (1.5.10-java)
|
|
125
|
+
oauth2 (0.9.2)
|
|
126
|
+
faraday (~> 0.8)
|
|
127
|
+
httpauth (~> 0.2)
|
|
128
|
+
jwt (~> 0.1.4)
|
|
129
|
+
multi_json (~> 1.0)
|
|
130
|
+
multi_xml (~> 0.5)
|
|
131
|
+
rack (~> 1.2)
|
|
98
132
|
oj (2.1.4)
|
|
99
133
|
pry (0.9.12.2)
|
|
100
134
|
coderay (~> 1.0.5)
|
|
@@ -123,18 +157,19 @@ GEM
|
|
|
123
157
|
hirb
|
|
124
158
|
simplecov
|
|
125
159
|
simplecov-html (0.7.1)
|
|
126
|
-
single_test (0.
|
|
127
|
-
rake
|
|
160
|
+
single_test (0.6.0)
|
|
161
|
+
rake
|
|
128
162
|
slop (3.4.6)
|
|
129
163
|
spoon (0.0.4)
|
|
130
164
|
ffi
|
|
131
165
|
test-unit (2.5.5)
|
|
132
|
-
thor (0.18.1)
|
|
133
166
|
turn (0.9.6)
|
|
134
167
|
ansi
|
|
135
168
|
webmock (1.13.0)
|
|
136
169
|
addressable (>= 2.2.7)
|
|
137
170
|
crack (>= 0.3.2)
|
|
171
|
+
websocket-driver (0.2.3)
|
|
172
|
+
websocket-driver (0.2.3-java)
|
|
138
173
|
yard (0.8.7)
|
|
139
174
|
|
|
140
175
|
PLATFORMS
|
|
@@ -142,8 +177,10 @@ PLATFORMS
|
|
|
142
177
|
ruby
|
|
143
178
|
|
|
144
179
|
DEPENDENCIES
|
|
180
|
+
api-auth!
|
|
145
181
|
bundler (~> 1.1)
|
|
146
182
|
curb
|
|
183
|
+
faye-websocket
|
|
147
184
|
httpclient
|
|
148
185
|
httpi!
|
|
149
186
|
jeweler!
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.4.0
|
data/bixby-common.gemspec
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = "bixby-common"
|
|
8
|
-
s.version = "0.
|
|
8
|
+
s.version = "0.4.0"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Chetan Sarva"]
|
|
12
|
-
s.date = "2013-08-
|
|
12
|
+
s.date = "2013-08-24"
|
|
13
13
|
s.description = "Bixby Common files/libs"
|
|
14
14
|
s.email = "chetan@pixelcop.net"
|
|
15
15
|
s.extra_rdoc_files = [
|
|
@@ -24,8 +24,13 @@ Gem::Specification.new do |s|
|
|
|
24
24
|
"VERSION",
|
|
25
25
|
"bixby-common.gemspec",
|
|
26
26
|
"lib/bixby-common.rb",
|
|
27
|
+
"lib/bixby-common/api/api_channel.rb",
|
|
28
|
+
"lib/bixby-common/api/encrypted_json_request.rb",
|
|
29
|
+
"lib/bixby-common/api/http_channel.rb",
|
|
27
30
|
"lib/bixby-common/api/json_request.rb",
|
|
28
31
|
"lib/bixby-common/api/json_response.rb",
|
|
32
|
+
"lib/bixby-common/api/rpc_handler.rb",
|
|
33
|
+
"lib/bixby-common/api/signed_json_request.rb",
|
|
29
34
|
"lib/bixby-common/bixby.rb",
|
|
30
35
|
"lib/bixby-common/command_response.rb",
|
|
31
36
|
"lib/bixby-common/command_spec.rb",
|
|
@@ -40,6 +45,12 @@ Gem::Specification.new do |s|
|
|
|
40
45
|
"lib/bixby-common/util/jsonify.rb",
|
|
41
46
|
"lib/bixby-common/util/log.rb",
|
|
42
47
|
"lib/bixby-common/util/log/filtering_layout.rb",
|
|
48
|
+
"lib/bixby-common/websocket/api_channel.rb",
|
|
49
|
+
"lib/bixby-common/websocket/async_response.rb",
|
|
50
|
+
"lib/bixby-common/websocket/client.rb",
|
|
51
|
+
"lib/bixby-common/websocket/message.rb",
|
|
52
|
+
"lib/bixby-common/websocket/request.rb",
|
|
53
|
+
"lib/bixby-common/websocket/response.rb",
|
|
43
54
|
"test/bixby_common_test.rb",
|
|
44
55
|
"test/command_response_test.rb",
|
|
45
56
|
"test/command_spec_test.rb",
|
|
@@ -55,13 +66,15 @@ Gem::Specification.new do |s|
|
|
|
55
66
|
]
|
|
56
67
|
s.homepage = "http://github.com/chetan/bixby-common"
|
|
57
68
|
s.require_paths = ["lib"]
|
|
58
|
-
s.rubygems_version = "
|
|
69
|
+
s.rubygems_version = "2.0.3"
|
|
59
70
|
s.summary = "Bixby Common"
|
|
60
71
|
|
|
61
72
|
if s.respond_to? :specification_version then
|
|
62
|
-
s.specification_version =
|
|
73
|
+
s.specification_version = 4
|
|
63
74
|
|
|
64
75
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
|
76
|
+
s.add_runtime_dependency(%q<faye-websocket>, [">= 0"])
|
|
77
|
+
s.add_runtime_dependency(%q<api-auth>, [">= 0"])
|
|
65
78
|
s.add_runtime_dependency(%q<multi_json>, [">= 0"])
|
|
66
79
|
s.add_runtime_dependency(%q<httpi>, [">= 0"])
|
|
67
80
|
s.add_runtime_dependency(%q<logging>, [">= 0"])
|
|
@@ -86,6 +99,8 @@ Gem::Specification.new do |s|
|
|
|
86
99
|
s.add_development_dependency(%q<curb>, [">= 0"])
|
|
87
100
|
s.add_development_dependency(%q<jruby-openssl>, [">= 0"])
|
|
88
101
|
else
|
|
102
|
+
s.add_dependency(%q<faye-websocket>, [">= 0"])
|
|
103
|
+
s.add_dependency(%q<api-auth>, [">= 0"])
|
|
89
104
|
s.add_dependency(%q<multi_json>, [">= 0"])
|
|
90
105
|
s.add_dependency(%q<httpi>, [">= 0"])
|
|
91
106
|
s.add_dependency(%q<logging>, [">= 0"])
|
|
@@ -111,6 +126,8 @@ Gem::Specification.new do |s|
|
|
|
111
126
|
s.add_dependency(%q<jruby-openssl>, [">= 0"])
|
|
112
127
|
end
|
|
113
128
|
else
|
|
129
|
+
s.add_dependency(%q<faye-websocket>, [">= 0"])
|
|
130
|
+
s.add_dependency(%q<api-auth>, [">= 0"])
|
|
114
131
|
s.add_dependency(%q<multi_json>, [">= 0"])
|
|
115
132
|
s.add_dependency(%q<httpi>, [">= 0"])
|
|
116
133
|
s.add_dependency(%q<logging>, [">= 0"])
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
module Bixby
|
|
3
|
+
|
|
4
|
+
class APIChannel
|
|
5
|
+
|
|
6
|
+
include Bixby::Log
|
|
7
|
+
extend Bixby::Log
|
|
8
|
+
|
|
9
|
+
# Execute the given request
|
|
10
|
+
#
|
|
11
|
+
# @param [JsonRequest] json_request
|
|
12
|
+
#
|
|
13
|
+
# @return [JsonResponse] response
|
|
14
|
+
def execute(json_request)
|
|
15
|
+
raise NotImplementedError
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
module Bixby
|
|
3
|
+
class EncryptedJsonRequest < JsonRequest
|
|
4
|
+
|
|
5
|
+
def initialize(json_request, private_key, public_key, uuid="master")
|
|
6
|
+
self.operation = json_request.operation
|
|
7
|
+
self.params = json_request.params
|
|
8
|
+
|
|
9
|
+
# encrypt
|
|
10
|
+
data = json_request.to_json
|
|
11
|
+
@body = Bixby::CryptoUtil.encrypt(data, uuid, public_key, private_key)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_wire
|
|
15
|
+
@body
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
|
|
2
|
+
module Bixby
|
|
3
|
+
|
|
4
|
+
class HttpChannel < Bixby::APIChannel
|
|
5
|
+
|
|
6
|
+
def initialize(uri)
|
|
7
|
+
@uri = uri
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Execute the given request
|
|
11
|
+
#
|
|
12
|
+
# @param [JsonRequest] json_request
|
|
13
|
+
#
|
|
14
|
+
# @return [JsonResponse] response
|
|
15
|
+
def execute(json_request)
|
|
16
|
+
execute_internal(json_request)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Execute a download request
|
|
21
|
+
# NOTE: This method is only available on the HTTP Channel.
|
|
22
|
+
#
|
|
23
|
+
# @param [JsonRequest] json_request
|
|
24
|
+
# @param [Block] block
|
|
25
|
+
#
|
|
26
|
+
# @return [JsonResponse] response
|
|
27
|
+
def execute_download(json_request, &block)
|
|
28
|
+
execute_internal(json_request, &block)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
# Execute the request, optionally passing a block to handle the response
|
|
35
|
+
#
|
|
36
|
+
# @param [JsonRequest] json_request
|
|
37
|
+
# @param [Block] block
|
|
38
|
+
#
|
|
39
|
+
# @return [JsonResponse] response
|
|
40
|
+
def execute_internal(json_request, &block)
|
|
41
|
+
|
|
42
|
+
req = HTTPI::Request.new(:url => @uri, :body => json_request.to_wire)
|
|
43
|
+
|
|
44
|
+
# add in extra headers if we have a SignedJsonRequest (or anything which has additional headers)
|
|
45
|
+
if json_request.respond_to? :headers then
|
|
46
|
+
req.headers.merge!(json_request.headers)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
if not req.headers.include? "Content-Type" then
|
|
50
|
+
# add content-type if not set
|
|
51
|
+
# may be set when creating a signed request
|
|
52
|
+
req.headers["Content-Type"] = "application/json"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
if block then
|
|
56
|
+
# execute request with block
|
|
57
|
+
req.on_body(&block)
|
|
58
|
+
HTTPI.post(req)
|
|
59
|
+
return JsonResponse.new("success")
|
|
60
|
+
|
|
61
|
+
else
|
|
62
|
+
# execute normal req, and return parsed response
|
|
63
|
+
res = HTTPI.post(req).body
|
|
64
|
+
return JsonResponse.from_json(res)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
module Bixby
|
|
3
|
+
class RpcHandler
|
|
4
|
+
|
|
5
|
+
# Handle a request
|
|
6
|
+
#
|
|
7
|
+
# @param [JsonRequest] request
|
|
8
|
+
#
|
|
9
|
+
# @return [JsonResponse] response
|
|
10
|
+
def handle(request)
|
|
11
|
+
raise NotImplementedError
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Channel connect event
|
|
15
|
+
#
|
|
16
|
+
# NOTE: only used by WebSocket channels and generally only implemented by
|
|
17
|
+
# the server-side.
|
|
18
|
+
#
|
|
19
|
+
# @param [Bixby::JsonRequest] json_req
|
|
20
|
+
# @param [Bixby::APIChannel] api
|
|
21
|
+
def connect(json_req, api)
|
|
22
|
+
# no-op
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Channel disconnection event
|
|
26
|
+
# NOTE: only used by WebSocket channels and generally only implemented by
|
|
27
|
+
# the server-side.
|
|
28
|
+
#
|
|
29
|
+
# @param [Bixby::APIChannel] api
|
|
30
|
+
def disconnect(api)
|
|
31
|
+
# no-op
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
|
|
2
|
+
module Bixby
|
|
3
|
+
class SignedJsonRequest < JsonRequest
|
|
4
|
+
|
|
5
|
+
attr_accessor :headers
|
|
6
|
+
|
|
7
|
+
def initialize(json_request, access_key=nil, secret_key=nil)
|
|
8
|
+
@operation = json_request.operation
|
|
9
|
+
@params = json_request.params
|
|
10
|
+
@access_key = access_key
|
|
11
|
+
@secret_key = secret_key
|
|
12
|
+
@headers = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# api-auth requires a path
|
|
16
|
+
def path
|
|
17
|
+
"/api"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def body=(str)
|
|
21
|
+
@body = str
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def body
|
|
25
|
+
if @body.nil? then
|
|
26
|
+
hash = { :operation => operation, :params => params }
|
|
27
|
+
@body = MultiJson.dump(hash)
|
|
28
|
+
end
|
|
29
|
+
return @body
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def to_wire
|
|
33
|
+
ApiAuth.sign!(self, @access_key, @secret_key)
|
|
34
|
+
body
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -14,7 +14,7 @@ class CommandSpec
|
|
|
14
14
|
|
|
15
15
|
# Create new CommandSpec
|
|
16
16
|
#
|
|
17
|
-
# @
|
|
17
|
+
# @param [Hash] params Hash of attributes to initialize with
|
|
18
18
|
def initialize(params = nil)
|
|
19
19
|
return if params.nil? or params.empty?
|
|
20
20
|
params.each{ |k,v| self.send("#{k}=", v) if self.respond_to? "#{k}=" }
|
|
@@ -46,6 +46,27 @@ module Bixby
|
|
|
46
46
|
opts[:filename] ||= Bixby.path("var", "bixby-agent.log")
|
|
47
47
|
FileUtils.mkdir_p(File.dirname(opts[:filename]))
|
|
48
48
|
|
|
49
|
+
# configure stdout appender (used in debug modes, etc)
|
|
50
|
+
Logging.color_scheme( 'bright',
|
|
51
|
+
:levels => {
|
|
52
|
+
:info => :green,
|
|
53
|
+
:warn => :yellow,
|
|
54
|
+
:error => :red,
|
|
55
|
+
:fatal => [:white, :on_red]
|
|
56
|
+
},
|
|
57
|
+
:date => :blue,
|
|
58
|
+
:logger => :cyan,
|
|
59
|
+
:message => :magenta
|
|
60
|
+
)
|
|
61
|
+
Logging.appenders.stdout( 'stdout',
|
|
62
|
+
:auto_flushing => true,
|
|
63
|
+
:layout => Logging.layouts.pattern(
|
|
64
|
+
:pattern => pattern,
|
|
65
|
+
:color_scheme => 'bright'
|
|
66
|
+
)
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# configure rolling file appender
|
|
49
70
|
options = {
|
|
50
71
|
:keep => 7,
|
|
51
72
|
:roll_by => 'date',
|
|
@@ -54,7 +75,6 @@ module Bixby
|
|
|
54
75
|
:auto_flushing => true,
|
|
55
76
|
:layout => layout
|
|
56
77
|
}.merge(opts)
|
|
57
|
-
|
|
58
78
|
Logging.appenders.rolling_file("file", options)
|
|
59
79
|
|
|
60
80
|
Logging::Logger.root.add_appenders("file")
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
|
|
2
|
+
require "bixby-common/websocket/async_response"
|
|
3
|
+
require "api-auth"
|
|
4
|
+
|
|
5
|
+
module Bixby
|
|
6
|
+
module WebSocket
|
|
7
|
+
|
|
8
|
+
# WebSocket API channel
|
|
9
|
+
#
|
|
10
|
+
# Implements a simple request/response interface over a WebSocket channel.
|
|
11
|
+
# Requests can be sent in either direction, in a sync or async manner.
|
|
12
|
+
class APIChannel < Bixby::APIChannel
|
|
13
|
+
|
|
14
|
+
attr_reader :ws
|
|
15
|
+
|
|
16
|
+
def initialize(ws, handler)
|
|
17
|
+
@ws = ws
|
|
18
|
+
@handler = handler
|
|
19
|
+
@responses = {}
|
|
20
|
+
@connected = false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Perform RPC
|
|
24
|
+
|
|
25
|
+
# Execute the given request (synchronously)
|
|
26
|
+
#
|
|
27
|
+
# @param [JsonRequest] json_request
|
|
28
|
+
#
|
|
29
|
+
# @return [JsonResponse] response
|
|
30
|
+
def execute(json_request)
|
|
31
|
+
fetch_response( execute_async(json_request) )
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Execute the given request (asynchronously)
|
|
35
|
+
#
|
|
36
|
+
# @param [JsonRequest] json_request
|
|
37
|
+
#
|
|
38
|
+
# @return [String] request id
|
|
39
|
+
def execute_async(json_request)
|
|
40
|
+
request = Request.new(json_request)
|
|
41
|
+
id = request.id
|
|
42
|
+
@responses[id] = AsyncResponse.new(id)
|
|
43
|
+
|
|
44
|
+
EM.next_tick {
|
|
45
|
+
ws.send(request.to_wire)
|
|
46
|
+
}
|
|
47
|
+
id
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Fetch the response for the given request
|
|
51
|
+
#
|
|
52
|
+
# @param [String] request id
|
|
53
|
+
#
|
|
54
|
+
# @return [JsonResponse]
|
|
55
|
+
def fetch_response(id)
|
|
56
|
+
res = @responses[id].response
|
|
57
|
+
@responses.delete(id)
|
|
58
|
+
res
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# Handle channel events
|
|
63
|
+
|
|
64
|
+
def connected?
|
|
65
|
+
@connected
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Open
|
|
69
|
+
def open(event)
|
|
70
|
+
# TODO extract Agent ID, if Agent
|
|
71
|
+
logger.debug "new channel opened"
|
|
72
|
+
@connected = true
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Close
|
|
76
|
+
#
|
|
77
|
+
# Can be fired either due to disconnection or failure to connect
|
|
78
|
+
def close(event)
|
|
79
|
+
if @connected then
|
|
80
|
+
logger.debug "client disconnected"
|
|
81
|
+
@connected = false
|
|
82
|
+
@handler.new(nil).disconnect(self)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Message
|
|
87
|
+
#
|
|
88
|
+
# Fired whenever a message is received on the channel
|
|
89
|
+
def message(event)
|
|
90
|
+
logger.debug "got a message:\n#{event.data}"
|
|
91
|
+
req = Message.from_wire(event.data)
|
|
92
|
+
|
|
93
|
+
if req.type == "rpc" then
|
|
94
|
+
# Execute the requested method and return the result
|
|
95
|
+
json_response = @handler.new(req).handle(req.json_request)
|
|
96
|
+
|
|
97
|
+
# result = { :type => "rpc_result", :id => req.id, :data => json_response }
|
|
98
|
+
# ws.send(MultiJson.dump(result))
|
|
99
|
+
ws.send(Response.new(json_response, req.id).to_wire)
|
|
100
|
+
|
|
101
|
+
elsif req.type == "rpc_result" then
|
|
102
|
+
# Pass the result back to the caller
|
|
103
|
+
@responses[req.id].response = JsonResponse.from_json(req.body)
|
|
104
|
+
|
|
105
|
+
elsif req.type == "connect" then
|
|
106
|
+
@handler.new(req).connect(req.json_request, self)
|
|
107
|
+
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
|
|
2
|
+
require 'thread'
|
|
3
|
+
|
|
4
|
+
module Bixby
|
|
5
|
+
module WebSocket
|
|
6
|
+
|
|
7
|
+
# Asynchronously receive a response via WebSocket channel
|
|
8
|
+
class AsyncResponse
|
|
9
|
+
|
|
10
|
+
attr_reader :id
|
|
11
|
+
|
|
12
|
+
def initialize(id)
|
|
13
|
+
@id = id
|
|
14
|
+
@mutex = Mutex.new
|
|
15
|
+
@cond = ConditionVariable.new
|
|
16
|
+
@response = nil
|
|
17
|
+
@completed = false
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Set the response and signal any blocking threads
|
|
21
|
+
#
|
|
22
|
+
# @param [Object] obj result of request, usually a JsonResponse
|
|
23
|
+
def response=(obj)
|
|
24
|
+
@mutex.synchronize {
|
|
25
|
+
@completed = true
|
|
26
|
+
@response = obj
|
|
27
|
+
@cond.signal
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Has the request completed?
|
|
32
|
+
#
|
|
33
|
+
# @return [Boolean] true if completed
|
|
34
|
+
def completed?
|
|
35
|
+
@completed
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Retrieve the response, blocking until it is available
|
|
39
|
+
#
|
|
40
|
+
# @return [Object] response data
|
|
41
|
+
def response
|
|
42
|
+
return @response if @completed
|
|
43
|
+
@mutex.synchronize { @cond.wait(@mutex) }
|
|
44
|
+
return @response
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
end
|