bandshell 0.0.20 → 0.0.21

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