|
32 | 32 | this.lasterr = null |
33 | 33 | this.stopped = false |
34 | 34 | this.starting = false |
35 | | - this.starting_interfaces = false |
36 | 35 | this.start_callback = null |
37 | 36 | this._stop_callback = null |
38 | 37 | this.started = false |
|
44 | 43 | //this.actives = {} // maybe store all active requests here, for debugging purposes? eh? |
45 | 44 | this.on_status_change = null |
46 | 45 | 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... |
48 | 47 | this.urls = [] |
49 | 48 | if (this.port > 65535 || this.port < 1024) { |
50 | 49 | var err = 'bad port: ' + this.port |
|
112 | 111 | change: function() { |
113 | 112 | if (this.on_status_change) { this.on_status_change() } |
114 | 113 | }, |
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 | + } |
117 | 119 | var callback = this.start_callback |
118 | 120 | this.start_callback = null |
119 | 121 | this.registerIdle() |
120 | 122 | if (callback) { |
121 | 123 | callback(this.get_info()) |
122 | 124 | } |
| 125 | + this.change() |
123 | 126 | }, |
124 | 127 | error: function(data) { |
125 | | - chrome.power.releaseKeepAwake() |
| 128 | + if (this.opts.optPreventSleep) { |
| 129 | + chrome.power.releaseKeepAwake() |
| 130 | + } |
126 | 131 | this.interface_retry_count=0 |
127 | 132 | var callback = this.start_callback |
| 133 | + this.starting = false |
128 | 134 | this.start_callback = null |
129 | | - console.error(data) |
| 135 | + console.error('webapp error:',data) |
130 | 136 | this.lasterr = data |
131 | 137 | this.change() |
132 | 138 | if (callback) { |
133 | 139 | callback({error:data}) |
134 | 140 | } |
135 | 141 | }, |
136 | 142 | stop: function(reason) { |
| 143 | + console.log('webserver stop:',reason) |
| 144 | + if (this.starting) { |
| 145 | + console.error('cant stop, currently starting') |
| 146 | + return |
| 147 | + } |
137 | 148 | this.clearIdle() |
138 | | - |
139 | | - chrome.power.releaseKeepAwake() |
| 149 | + |
| 150 | + if (this.opts.optPreventSleep) { |
| 151 | + chrome.power.releaseKeepAwake() |
| 152 | + } |
140 | 153 | // TODO: remove hidden.html ensureFirewallOpen |
141 | 154 | // 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...') |
144 | 159 | this.change() |
145 | 160 | return |
146 | 161 | } |
|
191 | 206 | } |
192 | 207 | }, |
193 | 208 | 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 | + } |
196 | 213 | }, |
197 | 214 | 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') |
202 | 222 | } |
203 | | - this.stop('idle') |
204 | 223 | }, |
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 | + /* |
209 | 227 | if (clear_urls === undefined) { clear_urls = true } |
210 | 228 | if (clear_urls) { |
211 | 229 | 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 |
213 | 234 | } |
| 235 | + this.start_callback = callback |
| 236 | + this.stopped = false |
| 237 | + this.starting = true |
| 238 | + this.change() |
214 | 239 |
|
| 240 | + // need to setup some things |
215 | 241 | 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() |
251 | 245 | } |
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 ? |
255 | 265 | } |
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}) |
261 | 272 | } |
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) { |
265 | 279 | var host = this.get_host() |
266 | 280 | sockets.tcpServer.create({name:"listenSocket"},function(sockInfo) { |
267 | 281 | this.sockInfo = sockInfo |
| 282 | + var tryPort = this.computePortRetry(state.port_attempts) |
| 283 | + state.port_attempts++ |
| 284 | + console.log('attempting to listen on port',tryPort) |
268 | 285 | sockets.tcpServer.listen(this.sockInfo.socketId, |
269 | 286 | 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 | + ) |
276 | 304 | }.bind(this)); |
277 | 305 | }, |
| 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 | + }, |
278 | 333 | refreshNetworkInterfaces: function() { |
279 | 334 | // want to call this if we switch networks. maybe better to just stop/start actually... |
280 | 335 | this.urls = [] |
|
303 | 358 | } |
304 | 359 | } |
305 | 360 | }, |
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 | | - }, |
325 | 361 | bindAcceptCallbacks: function() { |
326 | 362 | sockets.tcpServer.onAcceptError.addListener(this.onAcceptError.bind(this)) |
327 | 363 | sockets.tcpServer.onAccept.addListener(this.onAccept.bind(this)) |
|
0 commit comments