Skip to content

Commit 779b294

Browse files
committed
add retry on available ports option
1 parent 7e42ce8 commit 779b294

File tree

3 files changed

+152
-93
lines changed

3 files changed

+152
-93
lines changed

background.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,17 @@ function launch(launchData) {
167167

168168
}
169169

170+
function teststart() {
171+
var opts = {}
172+
opts.port = 8887
173+
opts.optAllInterfaces = true
174+
opts.optTryOtherPorts = true
175+
opts.optRetryInterfaces = true
176+
opts.handlers = []
177+
window.webapp = new WSC.WebApplication(opts)
178+
webapp.start( function(result) { console.log('webapp start result',result) } )
179+
}
180+
170181
chrome.app.runtime.onLaunched.addListener(launch);
171182

172183
function get_webapp(opts) {

polymer-ui/index.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,18 @@ function create_polymer_elements() {
130130
observer: 'interfaceChange',
131131
value: localOptions['optAllInterfaces']
132132
},
133+
optTryOtherPorts: {
134+
type: Boolean,
135+
value: false
136+
},
137+
optStopIdleServer: { // ms until stop inactive server
138+
type: Number,
139+
value: 0
140+
},
141+
optRetryInterfaces: {
142+
type: Boolean,
143+
value: true
144+
},
133145
optPreventSleep: {
134146
type: Boolean,
135147
observer: 'preventSleepChange',

webapp.js

Lines changed: 129 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
this.lasterr = null
3333
this.stopped = false
3434
this.starting = false
35-
this.starting_interfaces = false
3635
this.start_callback = null
3736
this._stop_callback = null
3837
this.started = false
@@ -44,7 +43,7 @@
4443
//this.actives = {} // maybe store all active requests here, for debugging purposes? eh?
4544
this.on_status_change = null
4645
this.interfaces = []
47-
this.interface_retry_count = 0
46+
this.interface_retry_count = 0 // when no network interfaces are available, wait for the wifi to come online...
4847
this.urls = []
4948
if (this.port > 65535 || this.port < 1024) {
5049
var err = 'bad port: ' + this.port
@@ -112,35 +111,51 @@
112111
change: function() {
113112
if (this.on_status_change) { this.on_status_change() }
114113
},
115-
success: function(data) {
116-
this.updatedSleepSetting()
114+
start_success: function(data) {
115+
if (this.opts.optPreventSleep) {
116+
console.log('requesting keep awake system')
117+
chrome.power.requestKeepAwake(chrome.power.Level.SYSTEM)
118+
}
117119
var callback = this.start_callback
118120
this.start_callback = null
119121
this.registerIdle()
120122
if (callback) {
121123
callback(this.get_info())
122124
}
125+
this.change()
123126
},
124127
error: function(data) {
125-
chrome.power.releaseKeepAwake()
128+
if (this.opts.optPreventSleep) {
129+
chrome.power.releaseKeepAwake()
130+
}
126131
this.interface_retry_count=0
127132
var callback = this.start_callback
133+
this.starting = false
128134
this.start_callback = null
129-
console.error(data)
135+
console.error('webapp error:',data)
130136
this.lasterr = data
131137
this.change()
132138
if (callback) {
133139
callback({error:data})
134140
}
135141
},
136142
stop: function(reason) {
143+
console.log('webserver stop:',reason)
144+
if (this.starting) {
145+
console.error('cant stop, currently starting')
146+
return
147+
}
137148
this.clearIdle()
138-
139-
chrome.power.releaseKeepAwake()
149+
150+
if (this.opts.optPreventSleep) {
151+
chrome.power.releaseKeepAwake()
152+
}
140153
// TODO: remove hidden.html ensureFirewallOpen
141154
// also - support multiple instances.
142-
143-
if (! (this.started || this.starting)) {
155+
156+
if (! this.started) {
157+
// already stopped, trying to double stop
158+
console.warn('webserver already stopped...')
144159
this.change()
145160
return
146161
}
@@ -191,90 +206,130 @@
191206
}
192207
},
193208
registerIdle: function() {
194-
console.log('registerIdle')
195-
this._idle_timeout_id = setTimeout( this.checkIdle.bind(this), this.opts.optStopIdleServer )
209+
if (this.opts.optStopIdleServer) {
210+
console.log('registerIdle')
211+
this._idle_timeout_id = setTimeout( this.checkIdle.bind(this), this.opts.optStopIdleServer )
212+
}
196213
},
197214
checkIdle: function() {
198-
console.log('checkIdle')
199-
for (var key in this.streams) {
200-
console.log('hit checkIdle, but had streams. returning')
201-
return
215+
if (this.opts.optStopIdleServer) {
216+
console.log('checkIdle')
217+
for (var key in this.streams) {
218+
console.log('hit checkIdle, but had streams. returning')
219+
return
220+
}
221+
this.stop('idle')
202222
}
203-
this.stop('idle')
204223
},
205-
start: function(callback, clear_urls) {
206-
console.log('webapp.start',callback?'with callback':'no callback',clear_urls)
207-
208-
this.start_callback = callback
224+
start: function(callback) {
225+
this.lasterr = null
226+
/*
209227
if (clear_urls === undefined) { clear_urls = true }
210228
if (clear_urls) {
211229
this.urls = []
212-
this.urls.push({url:'http://127.0.0.1:' + this.port})
230+
}*/
231+
if (this.starting || this.started) {
232+
console.error("already starting or started")
233+
return
213234
}
235+
this.start_callback = callback
236+
this.stopped = false
237+
this.starting = true
238+
this.change()
214239

240+
// need to setup some things
215241
if (this.interfaces.length == 0 && this.opts.optAllInterfaces) {
216-
this.starting_interfaces = true
217-
if (this.interface_retry_count > 10) {
218-
// 10 seconds and still no interface, just start...
219-
this.error('could not find network interface. try turning off accessible to other computers option')
220-
this.starting_interfaces = false
221-
return
222-
}
223-
224-
// fetch interfaces and start again later...
225-
chrome.system.network.getNetworkInterfaces( function(result) {
226-
console.log('network interfaces',result)
227-
if (result) {
228-
for (var i=0; i<result.length; i++) {
229-
if (result[i].prefixLength < 64) {
230-
this.urls.push({url:'http://'+result[i].address+':' + this.port})
231-
this.interfaces.push(result[i])
232-
console.log('found interface address: ' + result[i].address)
233-
}
234-
}
235-
}
236-
// XXX interfaces can be length 0! if we just
237-
// booted and we have no interfaces ready yet (eg
238-
// not connected to wifi)
239-
240-
if (this.interfaces.length == 0) {
241-
this.interface_retry_count++
242-
setTimeout( function() {
243-
this.start(callback, false)
244-
}.bind(this), 1000 )
245-
} else {
246-
this.starting_interfaces = false
247-
this.start(callback, false)
248-
}
249-
}.bind(this))
250-
return
242+
this.getInterfaces({interface_retry_count:0}, this.startOnInterfaces.bind(this))
243+
} else {
244+
this.startOnInterfaces()
251245
}
252-
this.lasterr = null
253-
if (_DEBUG) {
254-
console.log('webapp attempt start with opts',this.opts)
246+
},
247+
startOnInterfaces: function() {
248+
// this.interfaces should be populated now (or could be empty, but we tried!)
249+
this.tryListenOnPort({port_attempts:0}, this.onListenPortReady.bind(this))
250+
},
251+
onListenPortReady: function(info) {
252+
if (info.error) {
253+
this.error(info)
254+
} else {
255+
console.log('listen port ready',info)
256+
this.port = info.port
257+
this.ensureFirewallOpen()
258+
//console.log('onListen',result)
259+
this.starting = false
260+
this.started = true
261+
console.log('Listening on','http://'+ this.get_host() + ':' + this.port)
262+
this.bindAcceptCallbacks()
263+
this.init_urls()
264+
this.start_success({urls:this.urls}) // initialize URLs ?
255265
}
256-
this.change()
257-
//if (this.lasterr) { return }
258-
if (this.starting || this.started) {
259-
this.error("already starting or started")
260-
return
266+
},
267+
init_urls: function() {
268+
this.urls = []
269+
this.urls.push({url:'http://127.0.0.1:' + this.port})
270+
for (var i=0; i<this.interfaces.length; i++) {
271+
this.urls.push({url:'http://'+this.interfaces[i].address+':' + this.port})
261272
}
262-
this.stopped = false
263-
this.starting = true
264-
this.change()
273+
return this.urls
274+
},
275+
computePortRetry: function(i) {
276+
return this.port + i*3 + Math.pow(i,2)*2
277+
},
278+
tryListenOnPort: function(state, callback) {
265279
var host = this.get_host()
266280
sockets.tcpServer.create({name:"listenSocket"},function(sockInfo) {
267281
this.sockInfo = sockInfo
282+
var tryPort = this.computePortRetry(state.port_attempts)
283+
state.port_attempts++
284+
console.log('attempting to listen on port',tryPort)
268285
sockets.tcpServer.listen(this.sockInfo.socketId,
269286
host,
270-
this.port,
271-
this.onListen.bind(this))
272-
var lasterr = chrome.runtime.lastError
273-
if (lasterr) {
274-
console.log('lasterr listen',lasterr)
275-
}
287+
tryPort,
288+
function(result) {
289+
var lasterr = chrome.runtime.lastError
290+
if (lasterr || result < 0) {
291+
console.log('lasterr listen on port',tryPort, lasterr, result)
292+
if (this.opts.tryOtherPorts && state.port_attempts < 5) {
293+
this.tryListenOnPort(state, callback)
294+
} else {
295+
var errInfo = {error:"Could not listen", attempts: state.port_attempts, code:result, lasterr:lasterr}
296+
//this.error(errInfo)
297+
callback(errInfo)
298+
}
299+
} else {
300+
callback({port:tryPort})
301+
}
302+
}.bind(this)
303+
)
276304
}.bind(this));
277305
},
306+
getInterfaces: function(state, callback) {
307+
chrome.system.network.getNetworkInterfaces( function(result) {
308+
console.log('network interfaces',result)
309+
if (result) {
310+
for (var i=0; i<result.length; i++) {
311+
if (result[i].prefixLength < 64) {
312+
this.interfaces.push(result[i])
313+
console.log('found interface address: ' + result[i].address)
314+
}
315+
}
316+
}
317+
318+
// maybe wifi not connected yet?
319+
if (this.interfaces.length == 0 && this.optRetryInterfaces) {
320+
state.interface_retry_count++
321+
if (state.interface_retry_count > 5) {
322+
callback()
323+
} else {
324+
setTimeout( function() {
325+
this.getInterfaces(state, callback)
326+
}.bind(this), 1000 )
327+
}
328+
} else {
329+
callback()
330+
}
331+
}.bind(this))
332+
},
278333
refreshNetworkInterfaces: function() {
279334
// want to call this if we switch networks. maybe better to just stop/start actually...
280335
this.urls = []
@@ -303,25 +358,6 @@
303358
}
304359
}
305360
},
306-
onListen: function(result) {
307-
this.ensureFirewallOpen()
308-
//console.log('onListen',result)
309-
this.starting = false
310-
var lasterr = chrome.runtime.lastError
311-
if (lasterr) {
312-
this.error({message:lasterr})
313-
} else if (result < 0) {
314-
this.error({message:'unable to bind to port',
315-
errno:result})
316-
} else {
317-
this.started = true
318-
var host = this.get_host()
319-
console.log('Listening on','http://'+ host + ':' + this.port)
320-
this.bindAcceptCallbacks()
321-
this.change()
322-
this.success({urls:this.urls})
323-
}
324-
},
325361
bindAcceptCallbacks: function() {
326362
sockets.tcpServer.onAcceptError.addListener(this.onAcceptError.bind(this))
327363
sockets.tcpServer.onAccept.addListener(this.onAccept.bind(this))

0 commit comments

Comments
 (0)