siriproxypm-clientstatecache 0.0.1
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.
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/lib/siriproxypm-clientstatecache.rb +307 -0
- data/siriproxypm-clientstatecache.gemspec +22 -0
- metadata +50 -0
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,307 @@
|
|
1
|
+
require 'cora'
|
2
|
+
require 'siriproxy/plugin_manager'
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
class SiriProxy::PluginManager::ClientStateCache < SiriProxy::PluginManager
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
###############################################
|
10
|
+
#initialization
|
11
|
+
###############################################
|
12
|
+
|
13
|
+
@@client_state = nil
|
14
|
+
|
15
|
+
#intialization
|
16
|
+
def initialize()
|
17
|
+
super() #calls load_plugins
|
18
|
+
init_client
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
def get_client
|
24
|
+
port, ip = Socket.unpack_sockaddr_in(@iphone_conn.get_peername)
|
25
|
+
return ip;
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
def init_client
|
31
|
+
if @@client_state == nil
|
32
|
+
#create hash of array of stack states: key is client (e.g. ipaddress) value is hash with
|
33
|
+
#key :activity the last time activity was registered from this client
|
34
|
+
@@client_state = {}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_client_state(symbol,val)
|
39
|
+
client = get_client()
|
40
|
+
if client != nil
|
41
|
+
@@client[client][symbol] = val
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_client_state(symbol)
|
46
|
+
result = nil
|
47
|
+
client = get_client()
|
48
|
+
if client != nil
|
49
|
+
result = @@client[client][symbol]
|
50
|
+
end
|
51
|
+
return result
|
52
|
+
end
|
53
|
+
|
54
|
+
###############################################
|
55
|
+
#loading of plugins
|
56
|
+
###############################################
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
def get_plugin_list
|
61
|
+
result = []
|
62
|
+
if (plugin_configs = get_app_config("plugins") ) != nil \
|
63
|
+
&& plugin_configs.respond_to?('each')
|
64
|
+
plugin_configs.each do |plugin_config|
|
65
|
+
if plugin_config == nil \
|
66
|
+
|| !plugin_config.respond_to?('has_key?') \
|
67
|
+
|| !plugin_config.has_key?('name') \
|
68
|
+
|| plugin_config["name"] == nil
|
69
|
+
next
|
70
|
+
end
|
71
|
+
result << plugin_config["name"]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
return result
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
def process_plugins(text)
|
79
|
+
result = nil
|
80
|
+
plugins = get_plugin_list
|
81
|
+
plugins.each do |plugin|
|
82
|
+
plugin_obj = instatiate_plugin(plugin)
|
83
|
+
if plugin_obj == nil || !plugin_obj.is_a?(SiriProxy::Plugin)
|
84
|
+
next
|
85
|
+
end
|
86
|
+
if result = plugin_obj.process(text)
|
87
|
+
break
|
88
|
+
end
|
89
|
+
end
|
90
|
+
return result
|
91
|
+
end
|
92
|
+
|
93
|
+
def instantiate_plugin(plugin)
|
94
|
+
plugins = get_app_config("plugins")
|
95
|
+
if plugins != nil && plugins.respond_to?('each')
|
96
|
+
plugins.each do |pluginConfig|
|
97
|
+
if pluginConfig.is_a? String
|
98
|
+
class_name = pluginConfig
|
99
|
+
name = pluginConfig
|
100
|
+
require_name = "siriproxy-#{class_name.downcase}"
|
101
|
+
elsif pluginConfig['name'] != nil && pluginConfig['name'].is_a?(String)
|
102
|
+
name =pluginConfig['name']
|
103
|
+
class_name = pluginConfig['name']
|
104
|
+
require_name = pluginConfig['require'] || "siriproxy-#{class_name.downcase}"
|
105
|
+
end
|
106
|
+
|
107
|
+
if name == plugin && require_name.length > 0 && class_name.length > 0
|
108
|
+
require require_name
|
109
|
+
if (klass = SiriProxy::Plugin.const_get(class_name)).is_a?(Class)
|
110
|
+
plugin_obj = klass.new(pluginConfig)
|
111
|
+
plugin_obj.manager = self
|
112
|
+
return plugin_obj
|
113
|
+
break
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
return nil
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
###############################################
|
123
|
+
#regexp and ip range helper functions
|
124
|
+
###############################################
|
125
|
+
|
126
|
+
#@todo. make sure it matches the range specifications in dnsmasq
|
127
|
+
def in_range(client,range)
|
128
|
+
range.split(",").each do |ranges|
|
129
|
+
pieces = ranges.split("-")
|
130
|
+
if pieces.count == 1 && pieces[0] == client
|
131
|
+
return true
|
132
|
+
elsif pieces.count == 2
|
133
|
+
addr = client.split(".")[3]
|
134
|
+
ip_beg = pieces[0].split(".")[3]
|
135
|
+
ip_end = pieces[1].split(".")[3]
|
136
|
+
if ip_beg != nil \
|
137
|
+
&& ip_end != nil \
|
138
|
+
&& addr != nil \
|
139
|
+
&& ip_beg <= addr \
|
140
|
+
&& addr <= ip_end
|
141
|
+
return true
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
return false
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
def text_matches(text,list, default_list = [],post =false)
|
150
|
+
if list == nil
|
151
|
+
list = default_list
|
152
|
+
elsif list.is_a?(String)
|
153
|
+
list = [list]
|
154
|
+
elsif !list.responds_to?('each')
|
155
|
+
list = default_list
|
156
|
+
end
|
157
|
+
list.each do |regexp|
|
158
|
+
if regexp == nil
|
159
|
+
next
|
160
|
+
end
|
161
|
+
if regexp.is_a?(String)
|
162
|
+
if regexp[0] == '/'
|
163
|
+
#try to make it into a regexp
|
164
|
+
regexp = eval regexp
|
165
|
+
elsif
|
166
|
+
regexp = Regexp.new("^\s*#{regexp}\s",true);
|
167
|
+
end
|
168
|
+
end
|
169
|
+
if regexp == nil || !regexp.is_a?(Regexp)
|
170
|
+
next
|
171
|
+
end
|
172
|
+
if post
|
173
|
+
if (match_data = regexp.match(text)) != nil
|
174
|
+
return match_data.post_match
|
175
|
+
end
|
176
|
+
else
|
177
|
+
if text.match(regexp)
|
178
|
+
return true
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
return false
|
183
|
+
end
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
###############################################
|
188
|
+
#convienence methods for client :activity state
|
189
|
+
###############################################
|
190
|
+
def close_connection
|
191
|
+
set_client_state(:activity,0)
|
192
|
+
end
|
193
|
+
|
194
|
+
def keep_open_connection
|
195
|
+
set_client_state(:activity,Time.now.to_i)
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
def has_open_connection
|
200
|
+
return ((open = get_app_config("open")) != nil) \
|
201
|
+
&& open.is_a?(Integer) \
|
202
|
+
&& activity = get_client_state(:activity) \
|
203
|
+
&& activity + open >= Time.now.to_i
|
204
|
+
end
|
205
|
+
|
206
|
+
|
207
|
+
###############################################
|
208
|
+
#convience methods for access application config
|
209
|
+
###############################################
|
210
|
+
|
211
|
+
def get_app_config(*args)
|
212
|
+
result = $APP_CONFIG
|
213
|
+
if args != nil \
|
214
|
+
&& (first_arg = args.unshift) != nil
|
215
|
+
result = result.const_get(first_arg)
|
216
|
+
args.each do |arg|
|
217
|
+
if arg == nil \
|
218
|
+
||config_data == nil \
|
219
|
+
|| !config_data.respond_to?('has_key?')\
|
220
|
+
|| !config_data.has_key?(arg)
|
221
|
+
result = nil
|
222
|
+
break
|
223
|
+
end
|
224
|
+
result = result[arg]
|
225
|
+
end
|
226
|
+
end
|
227
|
+
return result
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
|
232
|
+
|
233
|
+
###############################################
|
234
|
+
#main text processing
|
235
|
+
###############################################
|
236
|
+
|
237
|
+
def process(text)
|
238
|
+
result = nil
|
239
|
+
log "Processing '#{text}'"
|
240
|
+
do_call_backs
|
241
|
+
if has_open_connection
|
242
|
+
log "Connection is still open"
|
243
|
+
if (proc_text = requested(text)) == nil
|
244
|
+
#we may not need this block... if the text is stream in tokenized chunks to process
|
245
|
+
proc_text = text
|
246
|
+
end
|
247
|
+
else
|
248
|
+
if (proc_text = requested(text)) == nil
|
249
|
+
no_matches
|
250
|
+
return nil
|
251
|
+
end
|
252
|
+
end
|
253
|
+
log "Got Honey Command: #{proc_text}"
|
254
|
+
keep_open_connection
|
255
|
+
if result = is_goodbye(proc_text) \
|
256
|
+
|| result = process_plugins(proc_text)
|
257
|
+
self.guzzoni_conn.block_rest_of_session
|
258
|
+
else
|
259
|
+
log "No matches for '#{proc_text}' on honey"
|
260
|
+
prompt
|
261
|
+
end
|
262
|
+
send_request_complete_to_iphone
|
263
|
+
return result
|
264
|
+
end
|
265
|
+
|
266
|
+
def prompt
|
267
|
+
respond( "Hello. What did you want?",{})
|
268
|
+
end
|
269
|
+
|
270
|
+
def do_call_backs
|
271
|
+
if !@callback
|
272
|
+
return
|
273
|
+
end
|
274
|
+
log "Active callback found, resuming"
|
275
|
+
# We must set the active callback to nil first, otherwise
|
276
|
+
# multiple callbacks within one listen block won't work
|
277
|
+
callback = @callback
|
278
|
+
@callback = nil
|
279
|
+
callback.call(text)
|
280
|
+
return true
|
281
|
+
end
|
282
|
+
|
283
|
+
|
284
|
+
|
285
|
+
def is_goodbye(text)
|
286
|
+
result = false
|
287
|
+
goodbyes = get_app_config("pluginManager","goodbye")
|
288
|
+
if (result = text_matches(text,goodbyes))
|
289
|
+
close_connection
|
290
|
+
end
|
291
|
+
return result
|
292
|
+
end
|
293
|
+
|
294
|
+
|
295
|
+
|
296
|
+
|
297
|
+
#returns nil if we need to ignore this text. otherwise it returns the
|
298
|
+
#remainder of the text to be processed
|
299
|
+
def requested(text)
|
300
|
+
return text_matches(get_app_config("pluginManager","identifier"),['honey'],true)
|
301
|
+
end
|
302
|
+
|
303
|
+
|
304
|
+
|
305
|
+
|
306
|
+
|
307
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "siriproxypm-clientstatecache"
|
6
|
+
s.version = "0.0.1"
|
7
|
+
s.authors = ["litlfred"]
|
8
|
+
s.email = [""]
|
9
|
+
s.homepage = ""
|
10
|
+
s.summary = %q{A Client Caching Plugin Manager}
|
11
|
+
s.description = %q{Plugin manager which keeps state information across multiple connections on a single client }
|
12
|
+
|
13
|
+
s.rubyforge_project = "siriproxypm-clientstatecache"
|
14
|
+
|
15
|
+
s.files = `git ls-files 2> /dev/null`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/* 2> /dev/null`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/* 2> /dev/null`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
# specify any dependencies here; for example:
|
21
|
+
# s.add_development_dependency "rspec"
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: siriproxypm-clientstatecache
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- litlfred
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-12-07 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ! 'Plugin manager which keeps state information across multiple connections
|
15
|
+
on a single client '
|
16
|
+
email:
|
17
|
+
- ''
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- Gemfile
|
23
|
+
- Rakefile
|
24
|
+
- lib/siriproxypm-clientstatecache.rb
|
25
|
+
- siriproxypm-clientstatecache.gemspec
|
26
|
+
homepage: ''
|
27
|
+
licenses: []
|
28
|
+
post_install_message:
|
29
|
+
rdoc_options: []
|
30
|
+
require_paths:
|
31
|
+
- lib
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
requirements: []
|
45
|
+
rubyforge_project: siriproxypm-clientstatecache
|
46
|
+
rubygems_version: 1.8.10
|
47
|
+
signing_key:
|
48
|
+
specification_version: 3
|
49
|
+
summary: A Client Caching Plugin Manager
|
50
|
+
test_files: []
|