bandshell 0.0.20 → 0.0.21

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a37911deac89814c591f5910d62d06146e4cc2d5
4
+ data.tar.gz: 9023709058607adcc1abfe5493b68b1f1e9c4332
5
+ SHA512:
6
+ metadata.gz: 89bb7fe3021a873560f6665bf37c41cdab77aac97df8214cf4b89fdcaf3b92694fb8e22b15122ab35274d26903a3ad2d48bd0af37b2921be5b359abe8d9cb36a
7
+ data.tar.gz: ac6cb86538341b970d80c57cea477d04a71e5c72ed2f1b7aca0b24eaf292980e517ae7d613773f9cdc4e2a4478c6d6b2e5544ed88d486618a7c6681e3b9de003
@@ -0,0 +1,34 @@
1
+ # bandshell-timer.rb
2
+ # Usage: bandshell-timer.rb ConcertoURL
3
+ # Where ConcertoURL Looks like http://localhost:4567
4
+ #
5
+ # Periodically ping the bandshell web app so that background tasks
6
+ # may be performed. Called by bandshelld as a daemon.
7
+ require "net/http"
8
+
9
+ def linestamp
10
+ "bandshell-timer.rb ("+Time.now.to_s+"): "
11
+ end
12
+
13
+ puts ""
14
+ puts linestamp + "Bandshell timer starting up."
15
+ BandshellURL = ARGV[0]
16
+
17
+ if BandshellURL.nil? or BandshellURL.empty?
18
+ raise linestamp + "Parameter Bandshell URL is required."
19
+ end
20
+
21
+ puts linestamp + "connecting to bandshell at " + BandshellURL
22
+
23
+ StatusURI = URI.parse(BandshellURL+"/background-job")
24
+
25
+ loop do
26
+ sleep(5)
27
+ begin
28
+ response = Net::HTTP.get_response(StatusURI)
29
+ rescue Errno::ECONNREFUSED
30
+ puts linestamp + "Bandshell is not responding."
31
+ rescue SocketError
32
+ puts linestamp + "Could not connect to given URL."
33
+ end
34
+ end
data/bin/bandshelld CHANGED
@@ -6,6 +6,18 @@ require "rubygems"
6
6
  require "daemons"
7
7
  require "bandshell/application/app"
8
8
 
9
- Daemons.run_proc("bandshelld", :dir_mode => :system) do
10
- ConcertoConfigServer.run!
9
+ dir_mode = (ConcertoConfigServer.development? ? :normal : :system)
10
+
11
+ Daemons.run_proc("bandshelld", :log_output=>true, :dir_mode => dir_mode) do
12
+ ConcertoConfigServer.run!
11
13
  end
14
+
15
+ bandshell_url = "http://localhost:" + ConcertoConfigServer.settings.port.to_s
16
+
17
+ timer_argv = ARGV.dup
18
+ timer_argv << "--" unless timer_argv.include? "--"
19
+ timer_argv << bandshell_url
20
+
21
+ Daemons.run("bin/bandshell-timer.rb",
22
+ :log_output=>true, :dir_mode => dir_mode,
23
+ :ARGV => timer_argv)
@@ -3,4 +3,3 @@
3
3
  require 'bandshell/netconfig'
4
4
 
5
5
  Bandshell::configure_system_network
6
-
@@ -5,321 +5,449 @@ require 'json'
5
5
  require 'net/http'
6
6
  require 'ipaddress'
7
7
  require 'bandshell/netconfig'
8
+ require 'bandshell/hardware_api'
8
9
  require 'sys/uptime'
9
10
  require 'sys/proctable'
10
11
  include Sys
11
12
 
12
13
  class ConcertoConfigServer < Sinatra::Base
13
- # set paths relative to this file's location
14
- set :root, File.dirname(__FILE__)
15
-
16
- # listen on all IPv4 and IPv6 interfaces
17
- set :bind, '::'
18
-
19
- # push these over to netconfig.rb?
20
- # Our list of available physical-layer connection methods...
21
- CONNECTION_METHODS = [
22
- Bandshell::WiredConnection,
23
- Bandshell::WirelessConnection
24
- ]
25
- # ... and available layer-3 addressing methods.
26
- ADDRESSING_METHODS = [
27
- Bandshell::DHCPAddressing,
28
- Bandshell::StaticAddressing
29
- ]
30
-
31
- # Hosts we allow to access configuration without authenticating.
32
- LOCALHOSTS = [
33
- IPAddress.parse("127.0.0.1"),
34
- IPAddress.parse("::1")
35
- ]
36
-
37
- set :haml, { :format => :html5, :layout => :main }
38
-
39
- helpers do
40
- # Get the return value of the method on obj if obj supports the method.
41
- # Otherwise return the empty string.
42
- # This is useful in views where arguments may be of diverse types.
43
- def value_from(obj, method)
44
- if obj.respond_to? method
45
- obj.send method
46
- else
47
- ""
48
- end
49
- end
50
-
51
- # Enforce authentication on actions.
52
- # Calling from within an action will check authentication and return
53
- # 401 if unauthorized.
54
- def protected!
55
- unless authorized?
56
- response['WWW-Authenticate'] = \
57
- %(Basic realm="Concerto Configuration")
58
- throw(:halt, [401, "Not authorized\n"])
59
- end
60
- end
61
-
62
- # Check authorization credentials.
63
- # Currently configured to check if the REMOTE_ADDR is local and allow
64
- # everything if so. This permits someone at local console to configure
65
- # without the need for a password. Others must have the correct
66
- # password to be considered authorized.
67
- def authorized?
68
- ip = IPAddress.parse(request.env['REMOTE_ADDR'])
69
- password = Bandshell::ConfigStore.read_config(
70
- 'password', 'default'
71
- )
72
- if LOCALHOSTS.include? ip
73
- # allow all requests from localhost no questions asked
74
- true
75
- else
76
- @auth ||= Rack::Auth::Basic::Request.new(request.env)
77
- @auth.provided? && @auth.basic? && @auth.credentials && \
78
- @auth.credentials == ['root', password]
79
- end
80
- end
81
-
82
- # Get our base URL from wherever it may be stored.
83
- def concerto_url
84
- Bandshell::ConfigStore.read_config('concerto_url', '')
85
- end
86
-
87
- # Try to figure out what our current IPv4 address is
88
- # and return it as a string.
89
- def my_ip
90
- iface = Bandshell.configured_interface
91
- if iface
92
- iface.ip
93
- else
94
- "Network setup failed or bad configuration"
95
- end
96
- end
97
-
98
- # Check if we have something resembling a network connection.
99
- # This means we found a usable interface and it has an IPv4 address.
100
- def network_ok
101
- iface = Bandshell.configured_interface
102
- if iface
103
- if iface.ip != "0.0.0.0"
104
- true
105
- else
106
- false
107
- end
108
- else
109
- false
110
- end
111
- end
112
-
113
- # Check if we can retrieve a URL and get a 200 status code.
114
- def validate_url(url)
115
- begin
116
- # this will fail with Errno::something if server
117
- # can't be reached
118
- response = Net::HTTP.get_response(URI(url))
119
- if response.code != "200"
120
- # also bomb out if we don't get an OK response
121
- # maybe demanding 200 is too strict here?
122
- fail
123
- end
124
-
125
- # if we get here we have a somewhat valid URL to go to
126
- true
127
- rescue
128
- # our request bombed out for some reason
129
- false
130
- end
131
- end
132
- end
133
-
134
- get '/' do
135
- if concerto_url == ''
136
- redirect '/setup'
137
- else
138
- redirect '/player_status'
139
- end
140
- end
141
-
142
- # The local fullscreen browser will go to /screen.
143
- # We should redirect to the screen URL if possible.
144
- # Otherwise, we need to go to the setup page to show useful information
145
- # and allow for local configuration if needed/wanted.
146
- get '/screen' do
147
- # if we don't have a URL go to setup
148
- # if we do, check it out
149
- if concerto_url == ''
150
- redirect '/setup'
151
- else
152
- # check if the concerto server is reachable, if so redirect there
153
- # if not redirect to a local error message screen
154
- if validate_url(concerto_url)
155
- redirect concerto_url
156
- else
157
- redirect '/problem'
158
- end
159
- end
160
- end
161
-
162
- # Present a form for entering the base URL.
163
- get '/setup' do
164
- protected!
165
- if network_ok
166
- # Everything's up and running, we just don't know what
167
- # our URL should be.
168
- haml :setup
169
- else
170
- # The network settings are not sane, we don't have an IP.
171
- # Redirect the user to the network configuration page to
172
- # take care of this.
173
- redirect '/netconfig'
174
- end
175
- end
176
-
177
- # Save the Concerto base URL.
178
- post '/setup' do
179
- protected!
180
- url = params[:url]
181
- if validate_url(url)
182
- # save to the configuration store
183
- Bandshell::ConfigStore.write_config('concerto_url', url)
184
-
185
- # root will now redirect to the proper concerto_url
186
- redirect '/screen'
187
- else
188
- # the URL was no good, back to setup!
189
- # error handling flash something something something
190
- redirect '/setup'
191
- end
192
- end
193
-
194
- # render a page indicating that the concerto_url is no good.
195
- # this page redirects to / every 5 seconds
196
- get '/problem' do
197
- haml :problem
198
- end
199
-
200
- get '/netconfig' do
201
- protected!
202
-
203
- # parse existing config file (if any)
204
- # if there isn't one, nil will suffice because our
205
- # value_from(...) helper will return the empty string if a method
206
- # is not implemented. This is also how we get away with just having
207
- # one instance each of the config classes that are currently selected.
208
- begin
209
- cm, am = Bandshell.read_network_config
210
- rescue Errno::ENOENT
211
- cm = nil
212
- am = nil
213
- end
214
-
215
- # view will grab what it can from our existing
216
- # connection/addressing methods using value_from().
217
- haml :netsettings, :locals => {
218
- :connection_method => cm,
219
- :addressing_method => am
220
- }
221
- end
222
-
223
- # Given the name of a class, pick a class out of a list of allowed classes.
224
- # This is used for parsing the form input for network configuration.
225
- def pick_class(name, list)
226
- list.find { |klass| klass.basename == name }
227
- end
228
-
229
- # Extract arguments from a set of form data that are intended to go to a
230
- # specific network configuration class. These fields have names of the form
231
- # 'ClassName/field_name'; this function returns a hash in the form
232
- # { 'field_name' => 'value } containing the configuration arguments.
233
- def extract_class_args(params, target_class)
234
- result = { }
235
- params.each do |key, value|
236
- klass, arg = key.split('/', 2)
237
- if klass == target_class
238
- result[arg] = value
239
- end
240
- end
241
-
242
- result
243
- end
244
-
245
- # Set the arguments on an instance of a given configuration class.
246
- # This uses the safe_assign method that should be present in all
247
- # configuration classes to determine which values are allowed to be passed
248
- # via form fields (i.e. which ones are subject to validation)
249
- def do_assign(params, instance)
250
- safe = instance.safe_assign
251
-
252
- params.each do |param, value|
253
- if safe.include? param.intern
254
- instance.send((param + '=').intern, value)
255
- end
256
- end
257
- end
258
-
259
- # Process the form fields and generate a JSON network configuration file.
260
- post '/netconfig' do
261
- protected!
262
-
263
- # First we find the connection-method and addressing-method classes.
264
- cmclass = pick_class(params[:connection_type], CONNECTION_METHODS)
265
- fail "Connection method not supported" if cmclass.nil?
266
-
267
- amclass = pick_class(params[:addressing_type], ADDRESSING_METHODS)
268
- fail "Addressing method not supported" if amclass.nil?
269
-
270
- # ... and create some instances of them.
271
- cm = cmclass.new
272
- am = amclass.new
273
-
274
- # Now given the names of the specific classes the user has chosen,
275
- # extract the corresponding form fields.
276
- cmargs = extract_class_args(params, cmclass.basename)
277
- amargs = extract_class_args(params, amclass.basename)
278
-
279
- # Set properties on each instance given the form values passed in.
280
- do_assign(cmargs, cm)
281
- do_assign(amargs, am)
282
-
283
- # Save the configuration file.
284
- Bandshell.write_network_config(cm, am)
285
-
286
- # Reload network configuration.
287
- STDERR.puts "Trying to bring down the interface"
288
- if Bandshell.configured_interface
289
- Bandshell.configured_interface.ifdown
290
- end
291
- STDERR.puts "Rewriting configuration files"
292
- Bandshell::configure_system_network
293
- STDERR.puts "Bringing interface back up"
294
- Bandshell.configured_interface.ifup
295
-
296
- # Back to the network form.
297
- redirect '/netconfig' # as a get request
298
- end
299
-
300
- get '/password' do
301
- protected!
302
- haml :password
303
- end
304
-
305
- post '/password' do
306
- protected!
307
-
308
- if params[:newpass] != params[:newpass_confirm]
309
- # something something error handling something
310
- redirect '/password'
311
- end
312
-
313
- Bandshell::ConfigStore.write_config('password', params[:newpass])
314
- redirect '/setup'
315
- end
316
-
317
- #Shows uptime,firmware version, and general system and process information
318
- #Requires ffi, sys-uptime, and sys-proctable gems
319
- get '/player_status' do
320
- @proctable = ProcTable.ps
321
- haml :player_status
322
- end
323
-
324
- end
14
+ # default to production, not development
15
+ set :environment, (ENV['RACK_ENV'] || :production).to_sym
16
+
17
+ # set paths relative to this file's location
18
+ set :root, File.dirname(__FILE__)
19
+
20
+ # listen on all IPv4 and IPv6 interfaces
21
+ set :bind, '::'
22
+
23
+ # Provide an option to skip network settings when developing
24
+ set :no_netconfig, false
25
+
26
+ configure :development do
27
+ puts 'Bandshell Config Server starting in development mode.'
28
+ begin
29
+ require "sinatra/reloader"
30
+ register Sinatra::Reloader
31
+ rescue LoadError
32
+ puts ' Reloading is not enabled, however.'
33
+ puts ' You can enable limited app.rb reloading in development by'
34
+ puts ' installing the sinatra-contrib gem on your system.'
35
+ end
36
+ set :no_netconfig, true
37
+ end
38
+
39
+ # push these over to netconfig.rb?
40
+ # Our list of available physical-layer connection methods...
41
+ CONNECTION_METHODS = [
42
+ Bandshell::WiredConnection,
43
+ Bandshell::WirelessConnection
44
+ ]
45
+ # ... and available layer-3 addressing methods.
46
+ ADDRESSING_METHODS = [
47
+ Bandshell::DHCPAddressing,
48
+ Bandshell::StaticAddressing
49
+ ]
50
+
51
+ # Hosts we allow to access configuration without authenticating.
52
+ LOCALHOSTS = [
53
+ IPAddress.parse("127.0.0.1"), # ipv4
54
+ IPAddress.parse("::ffff:127.0.0.1"), # ipv6-mapped ipv4
55
+ IPAddress.parse("::1") # ipv6
56
+ ]
57
+
58
+ set :haml, { :format => :html5, :layout => :main }
59
+
60
+ helpers do
61
+ # Get the return value of the method on obj if obj supports the method.
62
+ # Otherwise return the empty string.
63
+ # This is useful in views where arguments may be of diverse types.
64
+ def value_from(obj, method)
65
+ if obj.respond_to? method
66
+ obj.send method
67
+ else
68
+ ""
69
+ end
70
+ end
71
+
72
+ # Enforce authentication on actions.
73
+ # Calling from within an action will check authentication and return
74
+ # 401 if unauthorized.
75
+ def protected!
76
+ unless authorized?
77
+ response['WWW-Authenticate'] = \
78
+ %(Basic realm="Concerto Configuration")
79
+ throw(:halt, [401, "Not authorized\n"])
80
+ end
81
+ end
82
+
83
+ # Check authorization credentials.
84
+ # Currently configured to check if the REMOTE_ADDR is local and allow
85
+ # everything if so. This permits someone at local console to configure
86
+ # without the need for a password. Others must have the correct
87
+ # password to be considered authorized.
88
+ def authorized?
89
+ ip = IPAddress.parse(request.env['REMOTE_ADDR'])
90
+ password = Bandshell::ConfigStore.read_config(
91
+ 'password', 'default'
92
+ )
93
+ if LOCALHOSTS.include? ip
94
+ # allow all requests from localhost no questions asked
95
+ true
96
+ else
97
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
98
+ @auth.provided? && @auth.basic? && @auth.credentials && \
99
+ @auth.credentials == ['root', password]
100
+ end
101
+ end
102
+
103
+ # Get our base URL from wherever it may be stored.
104
+ def concerto_url
105
+ Bandshell::ConfigStore.read_config('concerto_url', '')
106
+ end
107
+
108
+ # Try to figure out what our current IPv4 address is
109
+ # and return it as a string.
110
+ def my_ip
111
+ iface = Bandshell.configured_interface
112
+ if iface
113
+ iface.ip
114
+ else
115
+ "Network setup failed or bad configuration"
116
+ end
117
+ end
118
+
119
+ # Try to figure out what our current port is
120
+ # and return it as a string.
121
+ def my_port
122
+ settings.port
123
+ end
124
+
125
+ # Check if we have something resembling a network connection.
126
+ # This means we found a usable interface and it has an IPv4 address.
127
+ def network_ok
128
+ return true if settings.no_netconfig
129
+ iface = Bandshell.configured_interface
130
+ if iface
131
+ if iface.ip != "0.0.0.0"
132
+ true
133
+ else
134
+ false
135
+ end
136
+ else
137
+ false
138
+ end
139
+ end
140
+
141
+ # Check if we can retrieve a URL and get a 200 status code.
142
+ def validate_url(url)
143
+ begin
144
+ # this will fail with Errno::something if server
145
+ # can't be reached
146
+ response = Net::HTTP.get_response(URI(url))
147
+ if response.code != "200"
148
+ # also bomb out if we don't get an OK response
149
+ # maybe demanding 200 is too strict here?
150
+ fail
151
+ end
152
+
153
+ # if we get here we have a somewhat valid URL to go to
154
+ true
155
+ rescue
156
+ # our request bombed out for some reason
157
+ false
158
+ end
159
+ end
160
+ end
161
+
162
+ get '/' do
163
+ if concerto_url == ''
164
+ redirect '/setup'
165
+ else
166
+ redirect '/player_status'
167
+ end
168
+ end
169
+
170
+ # The local fullscreen browser will go to /screen.
171
+ # We should redirect to the screen URL if possible.
172
+ # Otherwise, we need to go to the setup page to show useful information
173
+ # and allow for local configuration if needed/wanted.
174
+ get '/screen' do
175
+ # if we don't have a URL go to setup
176
+ # if we do, check it out
177
+ if concerto_url == ''
178
+ redirect '/setup'
179
+ else
180
+ # check if the concerto server is reachable, if so redirect there
181
+ # if not redirect to a local error message screen
182
+ if validate_url(concerto_url)
183
+ if Bandshell::HardwareApi.attempt_to_get_screen_data! == :stat_success
184
+ # Render the authenticate view which includes js to authenticate
185
+ # the browser and then redirect to the frontend.
186
+ @display_temp_token = nil # Disable the other features of the view
187
+ return haml :authenticate
188
+ else
189
+ # Authenticate action will manage the whole authentication process,
190
+ # picking up wherever we last left off.
191
+ redirect '/authenticate'
192
+ end
193
+ else
194
+ redirect '/problem'
195
+ end
196
+ end
197
+ end
198
+
199
+ # Present a form for entering the base URL.
200
+ get '/setup' do
201
+ protected!
202
+ if network_ok
203
+ # Everything's up and running, we just don't know what
204
+ # our URL should be.
205
+ @url=Bandshell::ConfigStore.read_config('concerto_url')
206
+ haml :setup
207
+ else
208
+ # The network settings are not sane, we don't have an IP.
209
+ # Redirect the user to the network configuration page to
210
+ # take care of this.
211
+ redirect '/netconfig'
212
+ end
213
+ end
214
+
215
+ # Save the Concerto base URL.
216
+ post '/setup' do
217
+ protected!
218
+ url = params[:url]
219
+ if validate_url(url)
220
+ # save to the configuration store
221
+ Bandshell::ConfigStore.write_config('concerto_url', url)
222
+
223
+ # root will now redirect to the proper concerto_url
224
+ redirect '/screen'
225
+ else
226
+ # the URL was no good, back to setup!
227
+ # error handling flash something something something
228
+ @errors = []
229
+ @errors << 'Failed to set URL: Could not connect to Concerto Server.'
230
+ @url = url
231
+ haml :setup
232
+ end
233
+ end
234
+
235
+ # render a page indicating that the concerto_url is no good.
236
+ # this page redirects to / every 5 seconds
237
+ get '/problem' do
238
+ haml :problem
239
+ end
240
+
241
+ get '/authenticate' do
242
+ # Following call will get a temp token if we need it
243
+ Bandshell::HardwareApi.attempt_to_get_screen_data!
244
+
245
+ # If we don't have a temp token that means we are authenticated
246
+ # or there was trouble communicating with the server.
247
+ if Bandshell::HardwareApi.have_temp_token?
248
+ @display_temp_token = Bandshell::HardwareApi.temp_token
249
+ end
250
+ return haml :authenticate
251
+ end
252
+
253
+ get '/authenticate.json' do
254
+ result = {:accepted => 0}
255
+ if Bandshell::HardwareApi.attempt_to_get_screen_data! == :stat_success
256
+ result[:accepted] = 1
257
+ result[:url] = Bandshell::HardwareApi.screen_url
258
+ result[:user] = "screen"
259
+ result[:pass] = Bandshell::HardwareApi.auth_token
260
+ end
261
+ content_type :json
262
+ result.to_json
263
+ end
264
+
265
+ get '/netconfig' do
266
+ protected!
267
+
268
+ # parse existing config file (if any)
269
+ # if there isn't one, nil will suffice because our
270
+ # value_from(...) helper will return the empty string if a method
271
+ # is not implemented. This is also how we get away with just having
272
+ # one instance each of the config classes that are currently selected.
273
+ begin
274
+ cm, am = Bandshell.read_network_config
275
+ rescue Errno::ENOENT
276
+ cm = nil
277
+ am = nil
278
+ end
279
+
280
+ # view will grab what it can from our existing
281
+ # connection/addressing methods using value_from().
282
+ haml :netsettings, :locals => {
283
+ :connection_method => cm,
284
+ :addressing_method => am
285
+ }
286
+ end
287
+
288
+ # Given the name of a class, pick a class out of a list of allowed classes.
289
+ # This is used for parsing the form input for network configuration.
290
+ def pick_class(name, list)
291
+ list.find { |klass| klass.basename == name }
292
+ end
293
+
294
+ # Extract arguments from a set of form data that are intended to go to a
295
+ # specific network configuration class. These fields have names of the form
296
+ # 'ClassName/field_name'; this function returns a hash in the form
297
+ # { 'field_name' => 'value } containing the configuration arguments.
298
+ def extract_class_args(params, target_class)
299
+ result = { }
300
+ params.each do |key, value|
301
+ klass, arg = key.split('/', 2)
302
+ if klass == target_class
303
+ result[arg] = value
304
+ end
305
+ end
306
+
307
+ result
308
+ end
309
+
310
+ # Set the arguments on an instance of a given configuration class.
311
+ # This uses the safe_assign method that should be present in all
312
+ # configuration classes to determine which values are allowed to be passed
313
+ # via form fields (i.e. which ones are subject to validation)
314
+ def do_assign(params, instance)
315
+ safe = instance.safe_assign
316
+
317
+ params.each do |param, value|
318
+ if safe.include? param.intern
319
+ instance.send((param + '=').intern, value)
320
+ end
321
+ end
322
+ end
323
+
324
+ # Process the form fields and generate a JSON network configuration file.
325
+ post '/netconfig' do
326
+ protected!
327
+
328
+ # First we find the connection-method and addressing-method classes.
329
+ cmclass = pick_class(params[:connection_type], CONNECTION_METHODS)
330
+ fail "Connection method not supported" if cmclass.nil?
331
+
332
+ amclass = pick_class(params[:addressing_type], ADDRESSING_METHODS)
333
+ fail "Addressing method not supported" if amclass.nil?
334
+
335
+ # ... and create some instances of them.
336
+ cm = cmclass.new
337
+ am = amclass.new
338
+
339
+ # Now given the names of the specific classes the user has chosen,
340
+ # extract the corresponding form fields.
341
+ cmargs = extract_class_args(params, cmclass.basename)
342
+ amargs = extract_class_args(params, amclass.basename)
343
+
344
+ # Set properties on each instance given the form values passed in.
345
+ do_assign(cmargs, cm)
346
+ do_assign(amargs, am)
347
+
348
+ # Save the configuration file.
349
+ Bandshell.write_network_config(cm, am)
350
+
351
+ # Reload network configuration.
352
+ STDERR.puts "Trying to bring down the interface"
353
+ if Bandshell.configured_interface
354
+ Bandshell.configured_interface.ifdown
355
+ end
356
+ STDERR.puts "Rewriting configuration files"
357
+ Bandshell::configure_system_network
358
+ STDERR.puts "Bringing interface back up"
359
+ Bandshell.configured_interface.ifup
360
+
361
+ # Back to the network form.
362
+ redirect '/netconfig' # as a get request
363
+ end
364
+
365
+ get '/password' do
366
+ protected!
367
+ haml :password
368
+ end
369
+
370
+ post '/password' do
371
+ protected!
372
+
373
+ if params[:newpass] != params[:newpass_confirm]
374
+ # something something error handling something
375
+ redirect '/password'
376
+ end
377
+
378
+ Bandshell::ConfigStore.write_config('password', params[:newpass])
379
+ redirect '/setup'
380
+ end
381
+
382
+ #Shows uptime,firmware version, and general system and process information
383
+ #Requires ffi, sys-uptime, and sys-proctable gems
384
+ get '/player_status' do
385
+ @proctable = ProcTable.ps
386
+ @on_off_rules = @@screen_on_off
387
+ haml :player_status
388
+ end
389
+
390
+ # Should be fetched at a regular interval by the background job
391
+ # to execute system maintenance functions such as updating configs
392
+ # from Concerto, and performing screen on/off control.
393
+ get '/background-job' do
394
+ if update_player_info
395
+ "Update executed"
396
+ else
397
+ "update_player_info failed."
398
+ end
399
+ end
400
+
401
+ # TODO: Refactor player settings management into a separate class
402
+
403
+ @@player_data_updated=Time.new(0)
404
+ @@screen_on_off=[{:action=>"on"}] # default to always-on
405
+
406
+ # Fetches the latest player settings from Concerto if the current
407
+ # settings are too old or an update is forced (force=true).
408
+ # TODO: Store settings in BandshellConfig (and update whenever they have
409
+ # changed) so that configs are immediately available at boot.
410
+ def update_player_info(force=false)
411
+ # TODO: Configurable update interval
412
+ if force or (@@player_data_updated < Time.now - 60*5)
413
+ data = Bandshell::HardwareApi::get_player_info
414
+ if data.nil?
415
+ puts "update_player_info: Error: Recieved null data from get_player_info!"
416
+ false
417
+ else
418
+ new_rules = parse_screen_on_off(data['screen_on_off'])
419
+ if new_rules.nil?
420
+ false
421
+ else
422
+ puts "update_player_info: Updating the rules!"
423
+ @@screen_on_off = new_rules
424
+ @@player_data_updated = Time.now
425
+ end
426
+ end
427
+ else
428
+ true
429
+ end
430
+ end
431
+
432
+ def parse_screen_on_off(data)
433
+ begin
434
+ rules = JSON.parse(data)
435
+ if rules.is_a? Array
436
+ return rules
437
+ else
438
+ puts "parse_screen_on_off: Recieved something other than an aray."
439
+ return nil
440
+ end
441
+ rescue
442
+ puts "parse_screen_on_off: invalid JSON recieved"
443
+ return nil
444
+ end
445
+ end
446
+
447
+ # Returns true if the screen should be turned on right now,
448
+ # according to the latest data recieved from concerto-hardware.
449
+ def screen_scheduled_on?
450
+ raise 'screen_scheduled_on?: TODO'
451
+ end
325
452
 
453
+ end